LevSelector.com New York
home > Actionscript

Actionscript (page under construction - still you may find it very useful)
On This Page     Other Pages

- intro
- books - links
- tutorials - tools
- More Links
- basics
- datatypes
- classes & objects
- running in flash & air
- casting
- arrays, sorting, hashes
- if, truth, switch, while
- break, continue
- try_catch_finally
- strings
- Math, Date
- create_objects_on_stage

- function reference
- function vars
- import/include
- multiple_inheritance
- files dirs
- database
- closures
- dynamic functions
- graphical_hierarchy
- manipulating graphical object
- Flash vs Flex
- Cloning Objects
- multiple timelines, this
- stage vs root

- threads
- memory
- performance
- fscommand
- keyboard - mouse -
- Mouse release outside
- Graphics
- timer
- prevent caching
- decompilers
- sound - video -
- E4X
- scenes
- embed_swf_info_html
- mxmlc
- classpath
- convert_mxml_to_as
- flash games
- miscellaneous

- xx
- xx
- xx
- xx

Intro ------------------------------

ActionScript - programming language to write Adobe Flash applications (animations, video/audio players, e-commerce applications, games, interactive business applications, etc.). Source files (*.as) are compiled/packaged into swf / swc files, which can be run in browsers (using Adobe Flash Player), or on desktop (using Adobe Air runtime).

To attract java programmers, Macromedia/Adobe have developed Flex - a downloadable collection of technologies (plugin for Eclipse IDE - including graphical designer, libraries (SDK), J2EE integration). Many programmers prefer Flex Builder development environment as opposed to Adobe Flash CS, which is more suited for graphical/animation designers.

Also Adobe made SDK free and open (comes with stand-alone compiler) - so it is possible to do ActionScript devlopment using only free tools.

Actionscript can also be used to write server-side applications (for example, using Macromedia Flash Communication Server MX).

Front-end applications written in Actionscript can directly communicate with server-side applications written in other languages (java, etc.) using different protocols.

Timeline:

Books ------------------------------

Also Flex:

 

Links ------------------------------

Tutorials ------------------------------

Tools ------------------------------

More Links ------------------------------

Basics ------------------------------

Short Actionscript tutorial.

Note: This page is mostly Flash CS3 - compatible. It covers AS 3.0 (which is very different from AS 2).

Actionscript syntax is very similar to Javascript and Java.
It also uses classes, objects, properties, methods, events.
It uses similar dot-syntax, and it uses similar comment notations:

/* multi-line
     comment */
// single line comment

truck.color = "yellow"; // property
function driveTruck( ):void { // defining a function
  truck.start(); // calling a method
  truck.accelerate(50);
}

Datatypes ------------------------------

Primitive data types

var v1:String="ABC";
var v2:Boolean=true;
var v3:Number=12; trace(v3);
var v3i:int=12; trace(v3i);
var v3ui:uint=12; trace(v3ui);
var v4:Array=["a","b","c"];
var v5:XML = <node><child/></node>;
//Note that the primitive XML is not quoted

Classes and Objects ------------------------------

Classes & Objects:

Class is a template for creating objects. Or its methods and properties can be used directly (like Math class). Usually you define each class in a separate file. A class can inherit from (extend) another class:

public class MySubClass extends MyBaseClass {
  override public function myfunction:void { ... } // note the use of word "override"
}

Note: available access attributes: public, private, protected, internal (default - internal).

constructor - is a method in a class with the same name as a class which is automatically called when an object (a class instance) is created.

If we have a class "Crane", then we can create a new object like this:

var mobileCrane:Crane = new Crane( );
mobileCrane.type = "mobile";
mobileCrane.height = "150";

And you can call methods:

mobileCrane.lift();
mobileCrane.lower();

We can define event listeners for this objects:

mobileCrane.addEventListener (CraneEvent.LIFT_FINISHED, eventListener);
mobileCrane.addEventListener (CraneEvent.LOWER_FINISHED, eventListener);

function eventListener (evt: CraneEvent):void {
   // execute some code in response to event
}

------------------------------

Example: MovieClip object:

var myMC:MovieClip = new MovieClip(); // calling a constructor
myMC.x = 100; // position on the stage
myMC.y = 100;
addChild(myMC); // add this movie to the display
myMC.gotoAndStop(5); // goto frame #5 and stop
myMC.addEventListener(Event.ENTER_FRAME, eventHandlerFunction);

Interfaces:

public interface IMonster {
  function getShot(damage:uint):void;
  function getCanShoot():Boolean;
}

public class spriteMouton extends MovieClip implements IMonster { ... }

 

Running in Flash CS3 ------------------------------

Writing/Running ActionScript in Adobe Flash CS:

Open FlashCS3, create a new Flash file, select the 1st keyframe on Layer 1,
open the Actions panel (press F9, or Windows >> Actions).
Note: Action panel has a list of classes, objects, events, methods.
Also clicking the down-pointing triangle on the upper-right corner opens the panel menu where you can set your preferences.

Copy-paste the following into the editor window:

// -------------------------------------------------------
//trace() - statement - to display something in the output panel.
trace("The sum of 2+2 is:");
trace(2+2);

var v1 = "mama"; trace(v1);

// typed variables
var v2:String = "line1 \"\" \n"
+ '\t line2 \'\' \n'
+ '\t\tline3 \\ \\ \n';
trace(v2 + "\ncrocodil\n"); // use "+" to concatenate strings

var v3:Number = 100 + 10.5; trace(v3 + 30);

var b1:Boolean = true; trace(b1); // true
// -------------------------------------------------------

Now press Ctrl-S to save the file.
Then press Ctrl-ENTER (or F9 or Control >> Test Movie).
You should see the output on the output panel (under the "output" tab).

 

Running in AIR ------------------------------

How to make your first "Hello World" application in Adobe AIR:

http://livedocs.adobe.com/air/1/devappsflash/help.html?content=FlashHelloWorld_1.html

Casting ------------------------------

With numbers you can use same common operators as in other languages:

+ - * / ++ -- += -= /= *=

Number types: int (integer - 32 bit with sign), uint *unsigned integer), Number - can be up to 53 bits

Data type conversions:

var s:String = "15.0";
var i:Number = 1;
i = Number(s) + 1; // 16 - convert string to Number
s = s + i; // 15.016 - convert number to string
trace(i);
trace(s);

var mycontainer:DisplayObject = new MovieClip(); // OK, because MovieClip inherits from DisplayObject
var mc:MovieClip = MovieClip(someObject); // throws an error if cast fails
var mc:MovieClip = someObject as MovieClip; // a bit slower, doesn't throw an error, returns null if cast fails

Casting to Dynamic classes:
If you attempt to pass a Date instance (Date is dynamic) into a method that accepts only Numbers, an error will occur.
But if you pass Date.doesnotexist - no error, because Date is dynamic, so the property will be created on the fly.

Often you need to invoke MovieClip methods on the parent(s) of your MovieClip object. Example:

MovieClip(parent.parent.parent).play();

Note: There are libraries to have formatting similar to "sprintf" - search Google for actionscript sprintf. Or use mx.Formatter.* from Flex SDK.

Arrays ------------------------------

Arrays

var a:Array = new Array(); // empty array
var a:Array = []; // empty array
var a:Array = new Array("aa","bb"); // array with some elements
var a:Array = ["a",2, true, new Object()];
trace(a[1]);
a = ["a","b","c"];
trace(a.toString()); // "a","b","c"
a = []; // make array empty

function my1(el:*, i:int, a:Array):void { trace("" + el + ", " + i); }
a.forEach(my1);

a.push("v1","v2");
a[a.length] = "v3";
a[100] = "fff"; // array will be extended to have 101 elements
a.unshift("zz");

for (var i:int = 0; i < a.length; i++) {trace(i + ": " + a[i]); }
for (i in a) {trace(i + ": " + a[i]); } // for - goes my index
for each (var v:* in a) { trace(v); } // for each - goes my values

a.splice(start,delete_count); // deleting
a.splice(start,0,"aa","bb"); // inserting
a.slice(start,end); // return a slice
a.pop();
a.shift();

var s:String = a.join("|"); // default separator is a comma
var a:Array = s.split("|"); //splitting a sting into an array

2-dim array:

var a:Array = new Array();
a.push([0,1,2]);
a.push([3,4,5]);
a.push([6,7,8]);

Copying array:

var a1:Array = [1,2,3];
var a2:Array = a1; // this doesn't create a new array - just creates a new pointer to the same array
var a3:Array = a1.concat(); // this creates a new copy of the array.
var a4:Array = a1.slice(); // this creates a new copy of the array.

Copying 2-dim array - use a recursive procedure. Or you can use some generic methods to copy objects - see a section on this topic lower on this page.

As array is a dynamic object - you can add properties to it.
To make sure that they will not show when you go through an array - you can set them as Enumerable or not.

var a:Array = ["a","b"];
a.prop1 = "crocodile";
a.setPropertyIsEnumerable("prop1", true);
var ii;
for (ii in a) {trace(ii + ": " + a[ii]); }
// traces 0,1,prop1
trace("==========");
a.setPropertyIsEnumerable("prop1", false);
for (ii in a) {trace(ii + ": " + a[ii]); }
// traces only 0,1


Sorting --------------------

Array Sorting ( see here:http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/Array.html )

Array.sort(compareFunction, sortOptions);

a.sort(); // sorts in place, default - ascii case-sensitive ascending sort
a.sort(Array.CASEINSENSITIVE);
a.sort(Array.DESCENDING | Array.NUMERIC );
a.sort(mySort); // we provide custom sort function

General form: Array.sort(compareFunction, sortOptions);

where:
   compareFunction - optional, accepts 2 args (A,B) and returns -1,0,+1
   sortOptions - optional, can be combined using bitwise OR - "|":
      1 - Array.CASEINSENSITIVE
      2 - Array.DESCENDING
      4 - Array.UNIQUESORT
      8 - Array.RETURNINDEXEDARRAY
    16 - Array.NUMERIC

Array.sortOn(fieldName:Object, options:Object = null):Array

Sort array of objects by some property(ies).

trees.sortOn("y", Array.DESCENDING | Array.NUMERIC); // sorts array of tree objects by their "y" property
Array.sortOn (["a", "b", "c"], [Array.DESCENDING, Array.NUMERIC, Array.CASEINSENSITIVE]); //sorts "a" using descending, "b" - numeric, "c" -case-insensitive sort

Array.reverse()

Reverses the array in place

 

 

Hashes ------------------------------

Associative array (hash):

var h:Object = new Object();
var h:Object = {};
var h:Object = { k1: "v1", k2: "v2" }; // object notation
h.k1 = "v1"; h.k2 = "v2"; h.k3 = "v3"; // property dot notation
h['k1']="v1"; h['k2'] = "v2"; h['k3'] = "v3"; // array accessor notation

trace(h.k2);

delete h.k2; // delete one key/value pair

if (h.hasOwnProperty('k1')) { ... } // test existance of a key 'k1'

for (var kk:String in h) { // similar to "foreach" in other languages
  trace(kk + " => " + h[kk]);
// note that here we have to use array accessor [] notation, not a dot-notation
                                      // to avoid validation during compile time

}

for each (var vv:* in h) { // for..each iterates through values (not keys)
   trace(vv); // values (1, 2, 3)
}

h = {}; // empty the hash
h = null; // cannot delete an object, only able to set to null

var h:Object = {};
h.s1 = {n1:"Jim",n2:"Smith"};
trace(h.s1.n2 + ", " + h.s1.n1); // Smith, Jim

or

var h:Object = {
  s1: {n1:"Jim",n2:"Smith"},
  s2: {n1:"Oleg",n2:"Kolosov"}
};
trace(h.s1.n2 + ", " + h.s1.n1); // Smith, Jim
trace(h.s2.n2 + ", " + h.s2.n1); // Kolosov, Oleg

Note: if you want to keep object refs as keys, you should use Dictionary instead of an Object:

var arr:Array = ["abc","def"];
var obj:Object = {k1:"v1"};
var dict:Dictionary = new Dictionary();
dict[arr] = "val1";
dict[obj] = "val2";

 

if else ------------------------------

if (n >= 10) {
   doSomething();
} else if (val == "myname") {
   doSomething();
} else if (n != 5) {
   doSomething();
} else {
   doSomething();
}

var boo:Boolean = false;
if(!boo) { ... }

if (e > 5 && e < 10) { ... }
if (e < 5 || e > 10) { ... }

var b = a>1 ? 1 : 0; // syntax: ( )? ... : ...

var mc:MovieClip = new MovieClip();
if (mc is MovieClip) { ... }

var s:String = "";
if(typeof(s) == "string"){ trace("var is a string"); }

Truth ------------------------------

if(blah) { ... } // can be false if blah is udefined or null or false or 0 or ""

// you can check explicitly:
if(blah != false) { ... }
if(blah != underfined) { ... }
if(blah != null) { ... }
if(blah != 0) { ... }
if(blah != "") { ... }

 

switch ------------------------------

switch(day) {
  case 0 : trace("Sunday");break;
  case 6 : trace("Saturday");break;
  default: trace("Work day");
}

while ------------------------------

while (i < 5) { trace(i); i++; }
do { trace(i); i++; } while(i<5);

// label, break to a label

break , continue ------------------------------

outerLoop: for (var i:int = 0; i < 10; i++) {
  for (var j:int = 0; j < 10; j++) {
    if ( (i == 8) && (j == 0)) {
      break outerLoop;
    }
    trace(10 * i + j);
  }
}

// continue - to skip the rest of the loop
var i:int = 0; while (i < 10) { if (i % 3 == 0) { i++; continue; } trace(i); i++; }

try catch finally ------------------------------

with (object:Object) { doSomething();doSomething(); }
try { doSomthing(); } finally { doSomthing(); }
try { doSomthing(); } catch(error:type1) { doSomthing(); } catch(error:type2) { doSomthing(); } finally { doSomthing(); }
throw new Error("Invalid email address");

Note: For asynchronous errors which can not be caught by try..catch block, you can create event handlers:

someobj.addEventListener(ErrorEvent.TYPE, handler); // ErrorEvent - flash.events.ErrorEvent
function handler(event:ErrorEvent):void {
  // handle error
}

someobj.dispatchEvent(new ErrorEvent("type")); // this is how to dispatch the error

 

Strings ------------------------------

Working with Strings:

property - only 1 property:

s.length

methods:

s.charAt(pos)
s.concat(s2)
s.slice(pos1,pos2)
s.split("|")
s.substring(pos1,pos2)
s.toLowerCase()
s.toUpperCase()

s = s1 + s2; // concatenating
s += s3; // concatenating

Convert number n to string s:

s = n; // error
s = ""+n; // OK
s = String(n); // OK
s = "" + n1 + n2; // n1 and n2 concatenated
s = "" + (n1 + n2); // n1 and n2 added

Regular expressions - similar to Perl (understands standard modifiers (g,i,x,s,m), parentheses, etc.).
The exec() method returns null if no match, or an object with array of matches.

http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/RegExp.html

var p:RegExp = /(gold).+(kruka)/is;
var s:String = " foo gold beee\n kruka car\n";
var res:Object = p.exec(s);
// exec() method
if(res) {
  for (var i in res) { trace(i + " => " + res[i]); }
  // 0 - full match, 1,2,... - in parentheses (equiv. to $1, $2, etc. in perl),
  // input property - original string
  // index property - position of matched substring

}

 

Math ------------------------------

Math class:

Constants: Math.PI, Math.E

abs(n), ceil(n), floor(n), round(n),
max(n1,n2,...), min(n1,n2,...), pow(n1,n2), random(), sqrt(n),
acos(n), asin(n), atan(n), atan2(y,x), cos(n), sin(n), tan(n)

 

Dates ------------------------------

Working with dates:

Final class Date: http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/Date.html

var mydate:Date = new Date(); // now
mydate = new Date(2000, 0, 1); // year(2000), month(0 = January), day(1)
mydate = new Date(65, 2, 6, 9, 30, 15, 0); // year(65=1965), month(2 = March), day(6), hour(9), min(30), sec(15), ms(0)
mydate = new Date(-14159025000); // milliseconds since january 1, 1970 - negtive means "before 1970"
trace(mydate); // Sun Jul 20 19:56:15 GMT-0700 1969

Examples of properties:

mydate.time - milliseconds since midnight January 1, 1970, universal time
mydate.date - day of the month (1..31)
mydate.day - day of the week (0-Sun, 2-Mon, etc.)
mydate.fullYear - 4-digit year
mydate.month - (0-11)
mydate.hours - (0-23)
mydate.minutes - (0-59)
mydate.seconds - (0-59)
mydate.timezoneOffset - The difference, in minutes, between universal time (UTC) and the computer's local time.

var time:int = mydate.time;
var month:int = mydate.month;

Examples of methods:

mydate.getDate(); // returns day of the month
mydate.getMinutes();
mydate.getFullYear();
...
mydate.setDate(day);
// sets day of the month, returns new time in ms since 1/1/1970
mydate.setMinutes(min,sec,ms);
// sets minutes, returns new time in ms
mydate.setTime(ms);
// setsand returns time in ms
...
mydate.parse(some_date_string);
// returns number of ms since 1/1/1970
Here are some supported formats:
   MM/DD/YYYY HH:MM:SS TZD
   HH:MM:SS TZD Day Mon/DD/YYYY
   Mon DD YYYY HH:MM:SS TZD
   Day Mon DD HH:MM:SS TZD YYYY
   Day DD Mon HH:MM:SS TZD YYYY
   Mon/DD/YYYY HH:MM:SS TZD
   YYYY/MM/DD HH:MM:SS TZD

mydate.valueOf(); // returns number of ms since 1/1/1970 for the mydate object
mydate.toString(); // example: Wed Apr 12 15:30:17 GMT-0700 2006
mydate.toTimeString(); // only time and timezone
mydate.toUTCString(); // in universal time (UTC)
mydate.toDateString(); // day and date only

Note: google for simple formatting functions for date, for example:
   function doubleDigitFormat(num:uint):String { if(num < 10) { return ("0" + num); } return num; }

Note: for calculating date differences you can use something like this:
   http://jeff.mxdj.com/datediff_for_actionscript.htm
Here is this code:

class DateFunction {
  // ------------------------------------------------------------
  // var n = dateDiff(datePart,date1,date2);
  // where valid dateParts: s, n (minutes), h,d,m,y */
  //-------------------------------------------------------------

  public static function dateDiff(datePart:String, date1:Date, date2:Date):Number {
    return getDatePartHashMap()[datePart.toLowerCase()](date1,date2);
    // the above return statement can be simplified if you split it in 3 line as following:
    //     var dphm:Object = getDatePartHashMap(); // returns hash object where values are function refs
    //     var fref:Function = dphm[datePart.toLowerCase()]; // get this function ref from the hash
    //     return fref(date1,date2); // call the function
  }

//-------------------------------------------------------------
// var n = getDatePartHashMap()["..."](date1,date2)
//-------------------------------------------------------------

private static function getDatePartHashMap():Object{
  var dpHashMap:Object = new Object();
  dpHashMap["s"] = getSeconds;
  dpHashMap["n"] = getMinutes;
  dpHashMap["h"] = getHours;
  dpHashMap["d"] = getDays;
  dpHashMap["m"] = getMonths;
  dpHashMap["y"] = getYears;
  return dpHashMap;
}

private static function compareDates(date1:Date,date2:Date):Number{ return date1.getTime() - date2.getTime(); }
private static function getSeconds(date1:Date,date2:Date):Number{ return Math.floor(compareDates(date1,date2)/1000); }
private static function getMinutes(date1:Date,date2:Date):Number{ return Math.floor(getSeconds(date1,date2)/60); }
private static function getHours(date1:Date,date2:Date):Number{ return Math.floor(getMinutes(date1,date2)/60); }
private static function getDays(date1:Date,date2:Date):Number{ return Math.floor(getHours(date1,date2)/24); }
private static function getMonths(date1:Date,date2:Date):Number{
  var yearDiff = getYears(date1,date2);
  var monthDiff = date1.getMonth() - date2.getMonth();
  if(monthDiff < 0){ monthDiff += 12; }
  if(date1.getDate()< date2.getDate()){ monthDiff -=1; }
  return 12 *yearDiff + monthDiff;
}
private static function getYears(date1:Date,date2:Date):Number{ return Math.floor(getDays(date1,date2)/365); }
} // end of class DateFunction

there is only one public method to interact with, that is dateDiff.
You can use it like this:

var now:Date = new Date();
var kaliBDay = new Date(2004,5,23,11,17);
trace(”Diff between “+ kaliBDay + ” and now ” +
DateFunction.dateDiff(”y”,now,kaliBDay) +” in years”);

 

Creates Objects On Stage ------------------------------

Creating Objects on Stage.

You can define object instance in the script (var mc:MovieClip = new MovieClip(); )
or you can create an object on the stage of Adobe Flash CS.

For example, select a drawing tool on the stage (say, rectangle) - and draw a rectangle. Then press F8 (Modify >> Convert to Symbol) - and select MovieClip and some name (say, n1)- and click OK. Then select the object on the stage, and in the properties panel (if it is not visible - press Ctrl-F3 or Window > Properties > Properties) - and type in some name for the instance (say, n2). Then create a new layer (say, Actions) and in this layer type:

n2.x=10;
n2.y=10;
n2.width = 200;
n2.height = 75;

and run it (ctrl-ENTER) .

Function Reference ------------------------------

Function reference to anonymous function

function f1(num){return num*2;}
var f2 = function(num){return num*3;} // f2 is a ref to an anonymous function
var i:Number = 3;
trace(f1(i)); // 6
trace(f2(i)); // 9

Good practice is to provide all types:

var f2:Function = function(num:Number):Number{return num*2;}

 

Function arguments and local variables ------------------------------

Function arguments and local variables:

  • Arguments are passed "by value". For simple variable types (Number, String, Boolean, etc) changing them in the function doesn't change the outside values. But for arrays, associative arrays (hashes), and other objects the argument is actually a reference to an object. So changing array elements inside the function will change the values in the original array object.
  • Variables defined inside a function are loal to this function and not visible from outside

var v1:Number = 1;
var v2:String = "A";
var v3:Array = [1,2,3];
trace("\nOutput:\n");
trace("before: " + v1 + ", " +v2+", "+v3); // v3 will expand into a list of array elements

function test(v1:Number, v2:String, v3:Array):String {
trace("in1: " + v1 + ", " +v2);
v1 = 2; v2 = "B"; // here v1 & v2 are local, so changing them doesn't change v1 & v2 outside
trace("in2: " + v1 + ", " +v2);
v3[1] *=2; // change external array element
var v4:String = "C + "; // local var
return v4 + v2;
}

var v4:String = test(v1,v2,v3);
trace("after: " + v1 + ", " +v2 + ", " +v3);
trace("v4: " + v4);

Output:

before: 1, A, 1,2,3
in1: 1, A
in2: 2, B
after: 1, A, 1,4,3
v4: C + B

------------------------------------------------------------------------------------------

Default values for optional parameters:

function f1(v1:Number, v2:String = "hello"):void { doSomething(); } // here v2 is optional

Note: parameters without default values are required - thus they should go before the optional parameters.

------------------------------------------------------------------------------------------

If you want the function to receive variable number of parameters,
you should use the syntax ...a, where a is a ref to array of parameters.

function f1(...a):void {trace(a.length +": "+ a);}
f1(); // 0:
f1(1); // 1: 1
f1("a", true, 0); // 3: a,true,0

 

import, include ------------------------------

Classes, Objects, Methods, external files - package, import, include.

Class is a blueprint for an object.
Object is an instance of a class.
Class hierarchy is organized into packages.
Package is simply a directory to store classes (each class in a separate file).
Class inheritance - the deeper class into a package - the more it inherits from parent classes.

import flash.utils.getTimer; // flash packages start with flash.*
import mx.automation.IAutomationObject;
// flex packages start with mx.*
import org.papervision3d.scenes.*;
// papervision packages

Using fully-qualified class name:

var mc:MovieClip = new flash.display.MovieClip();

Using short name:

import flash.display.MovieClip();
var mc:MovieClip = new MovieClip();

By the way, to include external ".as" file (not a package) you can do:

include "somefile.as";

Multiple Inheritance (not really) ------------------------------

Method - a function associated with a class.
Public methods - available for all objects outside the class.

// How to simulate multiple inheritance (modified from http://www.darronschall.com)

// In Animal.as
interface Animal {
    function setSpeechBubbleText( text:String ):void;
}

// In Animal_impl.as
public function setSpeechBubbleText( text:String ) {
    trace( "setting speech bubble text to: " + text );
}

// In Dog.as
public class Dog extends Sprite implements Animal {
    #include "Animal_impl.as";
    public function Dog() { /* constructor */ }
}

// In Cat.as
public class Cat extends Sprite implements Animal {
    #include "Animal_impl.as";
    public function Cat() { /* constructor */ }
}

If you ask the dog if he's an Animal - he'll surely respond that he is:

var dog:Dog = new Dog;
if ( dog is Animal ) { trace("bow wow!"); }

 

Files and Directories ------------------------------

Reading/writing files: http://labs.adobe.com/wiki/index.php/Apollo:Articles:Apollo_Local_File_System

Here is how to read a file

import flash.filesystem.FileMode;
import flash.filesystem.FileStream;
import flash.filesystem.File;

var myFile:File = File.appResourceDirectory; // Create out file object and tell our File Object where to look for the file
myFile = myFile.resolve("mySampleFile.txt"); // Point it to an actual file
var fileStream:FileStream = new FileStream(); // Create our file stream
fileStream.open(myFile, FileMode.READ); // other modes: WRITE, APPEND, UPDATE (read/write)
var fileContents:String = fileStream.readUTFBytes(fileStream.bytesAvailable); // Read the contens of the file
fileContents_txt.text = fileContents; // Display the contents in the TextArea on the stage

fileStream.close(); // Clean up and close the file stream

Example - write/read binary file

var file:File = File.desktopDirectory.resolve( "apollo test.dat" );
var stream:FileStream = new FileStream();
stream.open( file, FileMode.WRITE );

// Write some raw data to the file
stream.writeBoolean( false );
stream.writeInt( 1000 );
stream.writeByte( 0xC );

stream.close(); // Clean up

// now read this data from the file
stream.open( file, FileMode.READ );

trace( stream.readBoolean() ); // false
trace( stream.readInt() ); // 1000
trace( stream.readByte().toString( 16 ) ); // c

stream.close(); // Clean up

Working with directories:

var dir:File = File.desktopDirectory.resolve( "path/to/dir" );
if ( !dir.exists ) { dir.createDirectory(); trace( "Directory created." ); } else { trace( "Directory already exists." ); }
dir.listDirectoryAsync();
dir.addEventListener( FileListEvent.DIRECTORY_LISTING, handleDirectoryListing ); // wait until listing is done

private function handleDirectoryListing( event:FileListEvent ):void {
  trace( "Name\tSize\tDir?\tCreated On" ); // Display a header
  for each ( var item:File in event.files ) {
    trace( item.name + "\t" + item.size + "\t" + item.isDirectory + "\t" + item.creationDate );
  }
}

 

Database Connection ------------------------------

Connecting to a database.

It is possible to connect to a database directly from actionscript, for example: http://code.google.com/p/assql/ . This can be used for applications running locally (from Adobe AIR). But it is not a good idea to imbed database credentials into a swf file exposed to web.

So for web-based applications you need to generate a helper server-side application. You can create it using almost any technology - php, java servlet, ASP .NET, ColdFusion, Perl/cgi, server-side actionscript, etc. You can communicate with this helper application using HTTPService, WebService, or RemoteObject. Flex now has tools (wizards) to generate this server-side application.

Closures ------------------------------

Closures

Define a function within a function - and return the reference:

function new_greeting(name:String):Function {
  var s:String = "Hello " + name;
  var counter:int;
  function greet():void { trace(s + " -- " + ++counter); }
  return greet;
}

var v1:Function = new_greeting("person1");
var v2:Function = new_greeting("person2");

v1(); // Hello person1 -- 1
v2(); // Hello person2 -- 1
v1(); // Hello person1 -- 2
v2(); // Hello person2 -- 2

 

Dynamic Functions ------------------------------

Dynamic classes vs. sealed classes. Dynamic properties. Dynamic functions.

Example adding a method to an object:

function f1():String { return "Hello"; }
var o1:Object = new Object();
// it can be SomeOtherObject instead of just Object
o1.f1=f1;
//add function reference as a property to the object - this means "dynamic function"
trace(o1.f1()); //use the method

Note: these are equivalent:
this.path.reference
this["path"]["reference"]
this["path"].reference
this.path["reference"]


Example: create a dynamic property: this["myMovieClip"+ i]

Calling function by name:

var funcName:String = "doTrace";
function doTrace():void { trace("Hello"); }
this[funcName]();

Instantiate a class based on the value of a string:

var className = 'flash.net.LocalConnection'; // you need fully-qualified name
var ClassReference:Class = getDefinitionByName(className) as Class;

Note: Latest Actionscript 3.0 doesn't have eval() function.

 

Components ------------------------------

Components

A component is a widget, like a button or a menu bar. You can create it in Flash CS3, save as swc file - and then use in many projects.
http://www.adobe.com/devnet/flash/articles/creating_as3_components.html - tutorial

Graphical Hierarchy ------------------------------

Graphical hierarchy

      Object    
      |
EventDispatcher
   
      |
DisplayObject
   
/
Video
/
Bitmap
/
Shape

|
InteractiveObject

\
MorphShape
\
StaticText
   
/
TextField
|
DisplayObjectContainer
\
SimpleButton
 
/
Stage
|
Sprite
 \
Loader
 |
MovieClip
 
 
   

InteractiveObject - adds mouse/keyboard functionality
DisplayObjectContainer - adds containment for grouping
Sprite: adds dragability, button-style interaction features
MovieClip: adds timeline control

How swf file is formed: instance of stage class + instance of main class (Sprite or MovieClip).

instance of Stage
      |
instance of either Sprite or MovieClip (this is root)

In Flash CS3 - main class is called "document class" (Properties panel's "Document class" field)

Here is example of the code which creates some new objects - and then goes through the list of objects

// file Hello.as - saved in the same directory where my test.fla file is
// Then in Flash CS properties panel in "Document class" I write: Hello

package {
  import flash.display.*;
  
  public class Hello extends Sprite{
    public function Hello(){
      var mc1:BlueCircle = new BlueCircle();
      this.addChild(mc1);
   
      var mc2:MovieClip = new mc1.constructor();
      this.addChild(mc2);
      mc2.x = 100;
      mc2.y = 100;
   
      var bm:BitmapData = new BitmapData(mc1.width, mc1.height, true, 0);
      bm.draw(mc1);
      var mc3:Bitmap = new Bitmap(bm);
      this.addChild(mc3);
      mc3.x = 200;
      mc3.y = 200;
      trace(mc3);

      //trace(describeType(this)); // this line generates lots of XML output
   
      for (var i:Number=0; i<this.numChildren; i++){
        trace(this.getChildAt(i), this.getChildAt(i).name);
      }
    }
  }
}

Note: in the example above: you draw on BitmapData, then to show it - you create Bitmap object - and attach it to display (addChild(bm)).
Note: to remove from display - use removeChild(bm); To further remove from memory - set all references to null - and it will be garbage collected.

Frame scripts: the code inserted in "Actions" window in Flash will be associated with the corresponding frame. A main document class instance method will be created - and will be named frame1(), frame2(), etc. (starts with 1).

You can also add the frame code right from your main document .This is actually much better from maintenane perspective:

// Invoke doSomething when playhead reaches frame 1
// (Replaces any existing script on frame 1)

addFrameScript(0, doSomething);

// Remove frame 1's script
addFrameScript(0, null);

Code for library symbols: In Flash CS3 click on the symbol in the library, then click on top-right drop-down menu - and select "Linkage". Check the "Export for ActionScript" option, and enter the full path to your class definition in the "Class" textfield. Note: if the path is not found, flash will generate a linked class using the specified name and extending the specified base class

xxx

Graphical Properties ------------------------------

manipulating graphical object:

square.graphics.beginFill(0xffcc00);
square.graphics.lineStyle(2,0x000000);
square.graphics.drawRect(0,0,200,200);
square.graphics.endFill();
addChild(square);
// run to see
// now change:

square.x=200;
square.y=50;
square.alpha = 0.5; // opacity
square.scaleX=1.5;
square.saleY=.5;
square.rotation=45;

xxx

Flash vs Flex ------------------------------

Flash CS vs Flex - 2 IDEs from Adobe

If you design your application in Flash CS - then in many cases you can build your animation without coding. You can drag and drop objects from the palettes or libraries to the stage, manipulate objects on the stage graphically, convert them to reusable symbols (often of type MovieClip), arrange events on the timeline using frames, use layers, group pieces into scenes for easy manipulation. You can define different transition and movement effects between frames. You can copy/export/import parts of the design as XML (for example, Copy Motion XML). You can import external libraries and resources - and save your work into *.fla project file, and publish into compressed *.swf file(s).

If you design in Flex - then the graphical interface of your application is recorded mostly using MXML (XML-based markup langage). You can manipulate positions, sizes, and properties of the graphical objects using the "Design" mode. The events and actions can be programmed in actionscript and included into MXML inside CDATA blocks, or in separate files.

http://www.adobe.com/devnet/flex/articles/paradigm.html

Here is a simple MXML application (from Flex SDK examples folder):

<?xml version="1.0"?>
       <!-- Simple example to demonstrate the Move effect. -->
       <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
 <mx:Script>
   <![CDATA[
 private function moveImage():void {
         myMove.end();
         myMove.xTo=mouseX-60; 
         myMove.play();
         }
         ]]>
   </mx:Script>
 <mx:Move id="myMove" target="{img}"/>
 <mx:Panel title="Move Effect Example" width="95%" height="95%" 
         paddingTop="5" paddingLeft="10" paddingRight="10" paddingBottom="5">
 <mx:Text width="100%" color="blue" 
         text="Click anywhere on the canvas to move the phone horizontally to that position"/>
 <mx:Canvas id="canvas" width="100%" height="100%" mouseDown="moveImage();">
 <mx:Image id="img" source="@Embed(source='assets/Nokia_6630.png')"/>
 </mx:Canvas>
           
   </mx:Panel>
   </mx:Application>

 

Copying Objects ------------------------------

Copying (cloning) objects:

For simple objects you can either write your own recursive procedure, or do something like this:

import flash.utils.ByteArray;
function myclone(source:Object):* {
  var ba:ByteArray = new ByteArray();
  ba.writeObject(source);
  ba.position = 0;
  return(ba.readObject());
}

Note: the above method will not work properly for DisplayObjects, or for any object which need to keep references to specific instances (because the method creates fresh copies of everything).

Note: you may also have a problem casting the clone into the right class. To resolve this you may add a line like this:

flash.net.registerClassAlias("com.tests.TestClass",TestClass);

Here is an example on how to create a symbol in one swf file - and then load it into another file:
(from http://darylteo.com/blog/2007/11/16/abstracting-assets-from-actionscript-in-as30-asset-libraries/):

create a Circle (of class "Circle") - and save as circle.swf
Then you can laod and use it as following:

var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, assetLoaded, false, 0, true);
loader.load(new URLRequest("circle.swf");
stop();

function assetLoaded(e:Event):void{
  var circle:Class = e.target.applicationDomain.getDefinition("Circle");
  for(var i:int = 0;i<10;i++){
    this.addChild(temp);
    temp.x = Math.random()*300;
    temp.y = Math.random()*300;
  }
}

Yet another method of copying is to use Bitmap object:

public function copyBitmap(o1: DisplayObject) : Bitmap {
  var data : BitmapData = new BitmapData(o1.width, o1.height, true, 0);
  data.draw(o1);
  var o2: Bitmap = new Bitmap(data);
  return o2;
}

Yet another method is to do 2 steps. First, create a new object by calling a constructor: objref.constructor(). Then copy the properties one by one (same as you would do with a hash). Here is an example from http://www.senocular.com/flash/actionscript.php?file=ActionScript_3.0/com/senocular/display/duplicateDisplayObject.as

package com.senocular.display {

  import flash.display.DisplayObject;
  import flash.geom.Rectangle;
  import flash.system.Capabilities; // version check for scale9Grid bug

  // duplicateDisplayObject (similar to duplicateMovieClip in AVM1)
  // creates and returns a duplicate of the DisplayObject (target).
  // similar to duplicateMovieClip in AVM1. If using Flash 9, make sure
  // you export for ActionScript the symbol you are duplicating
  // if parameter autoAdd if true, adds the duplicate to the display list

  public function duplicateDisplayObject(target:DisplayObject, autoAdd:Boolean = false):DisplayObject {
    var targetClass:Class = Object(target).constructor;
    var duplicate:DisplayObject = new targetClass() as DisplayObject;
  
    // duplicate properties
    duplicate.transform = target.transform;
    duplicate.filters = target.filters;
    duplicate.cacheAsBitmap = target.cacheAsBitmap;
    duplicate.opaqueBackground = target.opaqueBackground;
    if (target.scale9Grid) {
      var rect:Rectangle = target.scale9Grid;
  
      if (Capabilities.version.split(" ")[1] == "9,0,16,0"){
        // Flash 9 bug where returned scale9Grid as twips
        rect.x /= 20, rect.y /= 20, rect.width /= 20, rect.height /= 20;
      }
  
      duplicate.scale9Grid = rect;
} // add to target parent's display list // if autoAdd was provided as true if (autoAdd && target.parent) { target.parent.addChild(duplicate); } return duplicate; } // function } // package

Some good links:

Multiple Timelines ------------------------------

Multiple Timelines

Basic operations within a timeline: gotoAndStop(), gotoAndPlay(), stop(), play(), nextFrame(), prevFrame()

You can manipulate particular movieclip like this: mc1.gotoAndStop();

You can use relative or absolute paths to refer to an object:

this = current timeline
root = main timeline
parent = parent timeline

Here is an example of nested movie-clips:

Stage instance

root (main timeline)

mc1

 

mc2

mc21

Here is how to reference objects from above example using absolute or relative paths:

Absolute paths relative paths (from mc2)
root
MovieClip(root).mc1
MovieClip(root).mc2
MovieClip(root).mc2.mc21
parent
MovieClip(parent).mc1
this
mc21

You can specify the action in the form: path.method(), for example:

mc1.gotoAndStop();
MovieClip(root).mc2.mc21.stop();
train_mc.wheels_mc.stop();
this.train_mc.wheels_mc.stop();

this --------------------

this = "whichever object or scope you are working with right now".

this.mc.width;
this.parent.mc.width;

 

Stage vs Root ------------------------------

Display List - instances of all displayed objects

Note: you can not access properties of Stage instance directly as Class properties or methods like this : trace(Stage.align); You need to reference stage instance from some display object, like this: trace(someDisplayObject.stage.align);

Note: the SWF file's main class must extend either Sprite or MovieClip, for example:

package {
  import flash.display.*
  import flash.text.TextField;

  public class Hello extends Sprite {

    public function Hello() {
      // do somethig here
    }
  }
}

Note: as we add children to the same container, they are automatically get assigned depth index (0,1,2,...). The first child gets 0, next - 1, etc. If children overlap, the one with higher index will be visible (will be on top of others). Here how you can see/manipulate things:

// c - container
trace(getChildIndex(child_ref)); // traces depth
trace(c.numChildren);
c.addChildAt(newChild, N); // insert new_obj at depth N
c.addChildAt(newChild, c.numChildren); // add on top - equivalent to c.addChild(newChild);
c.swapChildren(ch1,ch2); // exchanges depths of ch1 and ch2
c.setChildIndex(ch1,N);
c.setChildIndex(ch1,c.numChildren-1); // move ch1 to the top
c.removeChild(ch1);
c.removeChildAt(depth);
while(theParent.numChildren > 0) {theParent.removeChildAt(0);}
// children can be accessed by id or by name:
getChildAt(5).name = "SomeName";
getChildByName("SomeName").x = 100;

When you add an object to a container - it automatically detaches from its previous parent (if any).
If you move, rotate, or transform the container - child objects will also move/rotate/transform.

Threads ------------------------------

Actionscript 3 doesn't have support for multi-threading. So you can't take advantage of multiple CPU cores. No threads. But you can implement some work-arounds (pseudo-threading). Basically you emulate threads by chunking your code - and queuing the pieces:

Note (from Alex's blog):

1) Actionscript 3.0 is not multithreaded. In case of a pop-up creation - the next line will not run until after the popup returns from being created. The popup creation may return before creation complete because of invalidation, but if your code that follows the popup keeps running, you'll never see the popup.

2) Flash uses a deferred rendering model. Scripts run and update the display list objects, but the screen is not updated until scripts stop running, then the screen is rendered based on the current state of the display list objects. If your scripts do not stop running, Flash will kill the scripts after 60 seconds.

Memory Usage ------------------------------

Memory usage:

http://blog.pixelbreaker.com/flash/as30-memory-monitoring/ - here how to monitor it:

var mem:String = Number( System.totalMemory / 1024 / 1024 ).toFixed( 2 ) + 'Mb';
trace( mem ); // eg traces "24.94Mb"

The memory usage of components built with MXML tag is much bigger than that of components built using Actionscript:
http://dobeweb.com/2008/mxml-components-vs-actionscript-components–is-the-memory-usage-of-components-built-with-mxml-tag-bigger-than-that-of-components-built-in-actionscript.html

Memory optimization:
http://actionscript-blog.imaginationdev.com/12/memory-optimization-flash-action-script-3/ :
Problem: you can not free memory of a fixed property. Solution - make it a dynamic property, for example:

var playerObject:Object = new Object();
playerObject.sound = new Sound(); // create property at run time
...
delete playerObject.sound; // de-allocate memory

 

Performance ------------------------------

Performance:

Actionscript 3.0 is ~5-10 times slower than Java, and 100-500 times slower than C:
http://blog.richnetapps.com/index.php/as3-chess-engine-performance

This is because AS runs inside a virtual machine, and because it can't take advantage of multi-treading, multiple cores, or 64-bit architecture (the Number type in Flash is only 57 bits long).

Optimising performance: http://livedocs.adobe.com/flashlite/2/main/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&file=00000089.html

Guidelines for optimizing ActionScript performance for mobile devices (Flash Lite):

  • Keep the ActionScript as simple as possible.
  • Limit the number of loops that you use and the amount of code that each loop contains.
  • Stop frame-based looping as soon as it is no longer needed.
  • When possible, avoid string and array processing because it can be CPU-intensive.
  • Always try to access properties directly rather than using ActionScript getter and setter methods, which have more overhead than other method calls.
  • Manage events wisely and specifically. Keep your event listener arrays compacted by using conditions to check whether a listener exists (is not null) before calling it.
  • Delete variables or set them to null when you no longer need them. Doing this marks the data for garbage collection. Deleting variables helps optimize memory use during runtime, because unneeded assets are removed from the SWF file. It is better to delete variables than to set them to null.
  • Explicitly remove listeners from objects by calling removeListener() before garbage collection.
  • If you are dynamically calling a function and passing a fixed set of parameters, use call() instead of apply().
  • Make your namespaces (such as paths) more compact to save startup time. Every level in the package is compiled to an IF statement and causes a new Object() call, so having fewer levels in the path saves time. For example, a path with the levels com.xxx.yyy.aaa.bbb.ccc.functionName() causes an object to be instantiated for com, xxx, yyy, aaa, bbb, and ccc. Some Flash developers use preprocessor software to reduce the path to a unique identifier, such as 58923409876.functionName(), before compiling the SWF.
  • If your application consists of multiple SWF files that use the same ActionScript classes, you can exclude those classes from select SWF files during compilation. This can help reduce application download time and runtime memory requirements. For more information, see Excluding classes from compilation.
  • Avoid using Object.watch() and Object.unwatch(), since every change to an object property requires the player to determine whether a change notification must be sent.
    If ActionScript code that executes on a keyframe in the timeline requires more than 1 second to complete, consider splitting up that code to execute over multiple keyframes.
  • Remove trace() statements from your code when you publish the SWF file. To do this, select the Omit Trace Actions check box on the Flash tab in the Publish Settings dialog box.
  • Inheritance increases the number of method calls and uses more memory: a class that includes all the functionality it needs is more efficient at runtime than a class that inherits some of its functionality from a superclass. Therefore, you may need to make a design trade-off between extensibility of your classes and efficiency of your code.
  • When one SWF file loads another SWF file that contains a custom ActionScript class (for example, foo.bar.CustomClass) and then unloads the SWF file, the class definition remains in memory. To save memory, explicitly delete any custom classes in unloaded SWF files. Use the delete statement and specify the fully qualified class name, as the following example shows:
    delete foo.bar.CustomClass
  • Limit the use of global variables, because they are not garbage collected if the movie clip that defined them was removed.
  • Avoid using the standard user interface components (available in the Components panel in Flash Professional 8). These components are designed to run on desktop computers and are not optimized to run on mobile devices.
  • Whenever possible, avoid deeply nested functions.
  • Avoid referencing nonexistent variables, objects, or functions. Compared to the desktop version of Flash Player, Flash Lite 2.0 looks up references to nonexistent variables slowly, which can significantly affect application performance.

fscommand ------------------------------------------------------------------------------------------=

The flash.system package contains one package-level function, fscommand(), which facilitates communication between a SWF file and its container (with the browser, or, for stand-alone projectors, you can call other applications if you put them into the same folder).
http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/system/package.html

Example:

fscommand ("exec", "myappl.exe");

Here - an example of communication between JavaScript and Adobe Flash Player:
http://kb.adobe.com/selfservice/viewContent.do?externalId=tn_15683

Event Propagation --------------------

Three stages of event propagation:

 

Here is a great summary of common mouse and keyboard events - from http://www.senocular.com/flash/tutorials/as3withflashcs3/?page=3

Common Interactive Events
ActionScript 2 ActionScript 3 Differences
onPress "mouseDown" (MouseEvent.MOUSE_DOWN)  
onRelease "mouseUp" (MouseEvent.MOUSE_UP), "click" (MouseEvent.CLICK) The click event is most like onRelease since it depends on the object first receiving a mouseDown event whereas mouseUp can occur regardless of what was pressed
onReleaseOutside "mouseUp" (MouseEvent.MOUSE_UP) This has been removed, but using the mouseUp event with the stage (because of propagation) will allow you to detect when the mouse has been released outside of the object originally pressed
onRollOver "mouseOver" (MouseEvent.MOUSE_OVER), "rollOver" (MouseEvent.ROLL_OVER) Two events can now be used for rolling over objects; mouseOver will propagate, rollOver will not
onRollOut "mouseOut" (MouseEvent.MOUSE_OUT), "rollOut" (MouseEvent.ROLL_OUT) Two events can now be used for rolling off of objects; mouseOut will propagate, rollOut will not
onDragOver "mouseOver" (MouseEvent.MOUSE_OVER), "rollOver" (MouseEvent.ROLL_OVER) Detecting a "drag" will have to be done manually in combination with the mouseDown event.
onDragOut "mouseOut" (MouseEvent.MOUSE_OUT), "rollOut" (MouseEvent.ROLL_OUT) Detecting a "drag" will have to be done manually in combination with the mouseDown event.
mouseDown "mouseDown" (MouseEvent.MOUSE_DOWN) Now only works when the mouse is over the object dispatching the event (like onPress); normal objects cannot be made listeners of the Mouse to be able to recieve this event, only InteractiveObject instances can
mouseUp "mouseUp" (MouseEvent.MOUSE_UP) Now only works when the mouse is over the object dispatching the event (like onRelease but not requiring that the object be clicked first); normal objects cannot be made listeners of the Mouse to be able to recieve this event, only InteractiveObject instances can
mouseMove "mouseMove" (MouseEvent.MOUSE_MOVE) Now only works when the mouse is over the object dispatching the event; normal objects cannot be made listeners of the Mouse to be able to recieve this event, only InteractiveObject instances can
onKeyDown "keyDown" (KeyboardEvent.KEY_DOWN) Object must now have focus to receive this event; normal objects cannot be made listeners of the Key to be able to recieve this event, only InteractiveObject instances can
onKeyUp "keyUp" (KeyboardEvent.KEY_UP) Object must now have focus to receive this event; normal objects cannot be made listeners of the Key to be able to recieve this event, only InteractiveObject instances can

 

Keyboard Events ------------------------------

Keyboard Events

KEY_DOWN, KEY_UP

event.keyCode - actual char which was pressed ("a" or "A", etc.)
event.keyCode - ascii code (for SHIFT it is 16, for a - 65, etc.)
If you want to monitor keyboard events only while being focused on a particular object:
s.focus;
stage.focus;

import flash.display.Sprite;
import flash.events.KeyboardEvent;
import flash.ui.Keyboard; // convenient names for non-alphanumeric keys

var s:Sprite = new Sprite();
addChild(s);

s.addEventListener(KeyboardEvent.KEY_DOWN, onKeyboardEvent);
s.addEventListener(KeyboardEvent.KEY_UP, onKeyboardEvent);

public function onKeyboardEvent(event:KeyboardEvent):void {
  switch(event.keyCode) { 
    case Keyboard.UP:    ball.y -=10; break;
    case Keyboard.DOWN:  ball.y +=10; break;
    case Keyboard.LEFT:  ball.x -=10; break;
    case Keyboard.RIGHT: ball.x +=10; break;
    default: break;
  }

}

 

Mouse Events ------------------------------

Mouse Events

CLICK, DOUBLE_CLICK, MOUSE_DOWN, MOUSE_MOVE, MOUSE_OUT, MOUSE_OVER, MOUSE_UP, MOUSE_WHEEL, ROLL_OUT,ROLL_OVER

import flash.display.Sprite;
import flash.events.MouseEvent;
var s:Sprite = new Sprite();
addChild(s);
s.addEventListener(MouseEvent.CLICK, onMouseEvent);
s.addEventListener(MouseEvent.DOUBLE_CLICK, onMouseEvent);
public function onMouseEvent(event:MouseEvent):void { ... }
mouse_x_pos = s.mouseX
mouse_y_pos = s.mouseY


Note: the "hand" cursor for mouse-over will not be visible unless the display object's buttonMode and useHandCursor properties are true (useHandCursor is true by default but buttonMode is not). Setting buttonMode to true will also enable a focused object to receive a click event if the space bar or the Enter key is pressed on the keyboard.

myButton.buttonMode = true;

To disable mouse handling in the object - and let it pass the even through to the object behind it - do this:

overlay.mouseEnabled = false;

To disable mouse handling in all children of a Display object instance:

myobj.mouseChildren = false;

In ActionScript 3, the mouseMove event for display objects is only triggered when the mouse is over the display object. If you need the mouseMove event to be more global - listen to the stage:

stage.addEventListener(MouseEvent.MOUSE_MOVE, anyMouseMove);
function anyMouseMove(event:MouseEvent):void { .. }

 

Mouse Release Outside ------------------------------

onReleaseOutside() is removed in AS3. So the workaround is the following:

Once you mouse-down on an object, you have to add an event to the stage through objectReference.stage.addEventListener and then handle it through a function within the button.

Then once it gets fired you remove the listener from the stage right away: stage.removeEventListener(MouseEvent.MOUSE_UP, releaseOutsideHandler);

Here is a simple example:

// simple class for button (release outside):

package {

  import flash.display.Sprite;
  import flash.events.MouseEvent;

  public class Btn extends Sprite{

    function Btn ():void {
      addEventListener(MouseEvent.MOUSE_DOWN, on_press);
    }

    function on_press(event:MouseEvent):void{
      trace("press");
      stage.addEventListener(MouseEvent.MOUSE_UP, on_release_outside);
    }

    function on_release_outside(event:MouseEvent):void{
      stage.removeEventListener(MouseEvent.MOUSE_UP, on_release_outside);
      if (event.target == this) 
        trace("release inside");
      else
        trace("release outside");
    } // function

  } // class

} // package 

 

Graphics ------------------------------

flash.display.Graphics - to draw lines, fill bitmaps with gradients, etc. (moveTo, lineTo, clear, beginFill, endFill, drawEllipse, drawCircle, drawRect, drawRoundRect, etc.)

Timer-based animation --------------------

Flash movie circles through its frames. If you have only 1 frame - it will re-enter it over and over again. So you can use ENTER_FRAME event as a timer. Very innacurate, though, because if the code in the frame takes too long - Flash player will wait up to 15 seconds to let the code to finish. On the other side, if the code takes very short time to run - Flash will not update the frame immediately - it will wait according to frame rate.

package {

  import flash.display.Sprite;
  import flash.events.Event;

  public class MyAnimation extends Sprite {
    private var ball:Sprite;
    
    public function MyAnimation() { init(); } // constructor

    private function init():void {
      ball = new Sprite();
      addChild(ball);
      ball.graphics.beginFill(0xff000000);
      ball.graphics.drawCircle(0,0,40);
      ball.graphics.endFill();
      ball.x = 20;
      ball.y = stage.stageHeight / 2;
      ball.addEventListener(Event.ENTER_FRAME, onEnterFrame);
    }

    private function onEnterFrame(event:Event):void {
      ball.x++;
    }

  } // class

} // package 

Another approach is to use Timer() class:

mytimer = new Timer(interval_in_ms, how_many_times);
mytimer.addEventListener(TimerEvent.TIMER, my_on_timer);
mytimer.start();
mytimer.stop();
event.updateAfterEvent(); // necessary to update the screen

Here is an example:

package {

  import flash.display.Sprite;
  import flash.utils.Timer;
  import flash.events.TimerEvent;

  public class Timer1 extends Sprite
  {
    private var mytimer:Timer;

    public function Timer1() { init(); } // constructor

    private function init():void {
      mytimer = new Timer(30,300); //every 30 millisec, 300 times
      mytimer.addEventListener(TimerEvent.TIMER, my_on_timer);
      mytimer.start();
    }

    private function my_on_timer(timer:TimerEvent):void {
      // do something
      event.updateAfterEvent(); // this is to update the screen

    }

  } // class

} // package 

Note: timer max frequency (min interval) in practice depends on the setting of the frame rate, and is ~ 1/10th of the frame rate. So if you want to set timer to do updates every 10 ms, then you need to set frame rate to 100 ms:

stage.frameRate = 10; // default is 12

Note: if you need your animation to move with the same speed on different computers, you can adjust the speed by measuring actual time:

time1 = getTimer(); // gives time in ms
...
time2 = getTimer();
step_to_make = velocity*(time2 - time1);

 

How To Prevent Caching of SWF files --------------------

How To Prevent Caching of SWF files in browser cache

1. Using http headers:

To prevent client browsers from caching the SWF file, try setting the following HTTP headers in the wrapper that returns the Flex application's SWF file Here are examples:
==================
//(in php syntax):
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
header("Cache-Control: no-store, no-cache, must-revalidate");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
==================
Cache-control: no-cache, no-store, must-revalidate, max-age=-1
Pragma: no-cache, no-store
Expires: -1
==================
HMLT page:
<HEAD>
...
<!-- BEGIN INSERT --><META HTTP-EQUIV="Expires" CONTENT="Mon, 04 Dec 1999 01:00:00 GMT"><!-- END INSERT -->
</HEAD>
<BODY>
...
</BODY>
<!-- BEGIN INSERT --><HEAD><META HTTP-EQUIV="PRAGMA" CONTENT="NO-CACHE"></HEAD><!-- END INSERT -->

2. Adding random parameter to the end of URL address in actionscript or javascript:

// var pageLink ='http://somedomain/somepath/somefile?key1=value1&key2=value2';

var cc = '&'; // use '?' if this will be the first parameter
var myURL = ...;
myURL += cc + "t=" + (new Date()).getTime());
myURL += cc + Math.random()*1000;

3. Using proxy page to set up HTTP headers:

Instead of loading the SWF directly, you load the php page which loads it with http headers set to avoid caching:

((swf_proxy.php))
<?php
$filename = "test_cache.swf";
header('Content-type: application/x-shockwave-flash');header("Expires: Thu, 01 Jan 1970 00:00:00 GMT, -1 ");
header("Cache-Control: no-cache, no-store, must-revalidate");
header("Pragma: no-cache");
$content = file_get_contents($filename);
echo$content;
?>

Read some discussions here:

 

SWF Decompilers and SWF protection

Decompilers:

Protection:

One simple trick to make your SWF files less accessible is to load them dynamically. Read section "Using Socket to Load Display Assets at Runtime" in O'Reilly book "Essential Actionscript 3.0" by Colin Moock (pp.796-807). After the content is loaded into the buffer:

Loader = new Loader();
loader.loadBytes(buffer);
loader.contentLoaderInfo.addEventListener(Event.INIT, assetInitListener);
private function assetInitListener(e:Event):void {
  addChild(loader.content);
} 

 

Play Sound --------------------

Play Sound

var song:Sound = new Sound();
var p:URLRequest = newURLRequest("/somedir/mysound.mp3");
song.load(p);
song.play();
// or simply
var song:Sound = new Sound(new URLRequest("/somedir/mysound.mp3"));
song.play();
trace(song.bytesTotal);

//Volume
var sc:SoundChannel = new SoundChannel();
sc = song.play();
var st:SoundTransform = new SoundTransform();
st.volume = 0.5
// 50%
sc.soundTransform = st;

Play Video --------------------

Play Video

import flash.video.FLVPlayback;
import flash.video.VideoScaleMode;
var v:FLVPlayback = new FLVPlayback();

var src:String = 'http://.../myfile.flv';
v.width = 320;
v.height = 240;
v.autoPlay = false;
v.scaleMode = VideoScaleMode.MAINTAIN_ASPECT_RATIO;
v.skinAutoHide = true;
v.skinBackgroundAlpha = .5;
v.skinBackgroundColor = 0xff0000;
v.source = src;
v.volume = .5;

xxx

E4X = ECMAScript for XML --------------------

E4X = ECMAScript for XML (E4X) Specification.

flash.xml.XMLDocument;

There are two primary, top level ActionScript classes that Flash uses to work with E4X XML: XML and XMLList.

var xml:XML = <inline> <example /> </inline>; // example of inline literal

Note: inline literal must have a single root node. So you cannot create an inline XMLList.

// Child elements accessible as
// properties of XML instance
var sport:XML =
   <sport>
   <name>Basketball</name>
   <players>men</players>
   <players>women</players>
   <nationalTV>NBC</nationalTV>
   <nationalTV>ESPN</nationalTV>
   </sport>;
trace(sport.players is XMLList); // true
trace(sport.players);
//output:
//   <players>men</players>
//   <players>women</players>
trace(sport.players[0] is XML); // true
trace(sport.players[0]); // traces "men" trace(sport.players[0].toString()); // traces "men"
trace(sport.players[0].toXMLString()); // traces "<players>men</players>"

Use (..) operator - to access children and all childrens children, for example:

trace(channel..title.toXMLString());

Use "@" prefix to access xml wattributes:

var item:XML =<item name="attribute"><name>element</name> </item>;
trace(item.name); // traces "element"
trace(item.@name); // traces "attribute"

Attributes form a list:

var images:XML = <images> <img href="image1.jpg" /> <img href="image2.jpg" /> <img href="image3.jpg" /> </images>;
trace(images.img.@href is XMLList); // true
trace(images.img.@href); // "image1.jpgimage2.jpgimage3.jpg"
trace(images.img.@href[0]); // "image1.jpg"

Name conflicts: in XML dot notaion you can use element names or methods (like name() , children(), attribute()). But what if the xml has an element called "name"? We have a conflict. Be cautious, put braces "()" after the name if you want to use the method.

Here - accessing elements with complex names:

var values:XML = <values for-example="see below"> <complex-name>simple value</complex-name> </values>;
// trace(values.@for-example); // Syntax error
trace(values.attribute("for-example")); // traces "see below"
// trace(values.complex-name); // Syntax error
trace(values.elements("complex-name")); // traces "simple value"

Filtering:

trace(grades.student.(name == "Michelle")); // find student with the name "Michelle"
trace(grades.student.quiz.(@num == "1"));
trace(grades.student.(name != "Michelle" && quiz.length() < 2));
trace(grades.student.(quiz.score == 90));
trace(grades.student.(quiz.(score == 90).length()));
var scoreCheck:int = 90;
trace(grades.student.(quiz.score == scoreCheck));

Define XML dynamically:

// Dynamic XML definition with braces
var elemName:String = "e1"; var attrName:String = "a1"; var attrValue:String = "v1"; var textNode:String = "text1";
var xml:XML =<{elemName} {attrName}={attrValue}> {textNode} </{elementName}>;
trace(xml.toXMLString()); // traces "<elem attr="value">text</elem>"

// XML generation with strings
var tagContents:String = "elem att=\"value\"";
var xml:XML = new XML("<" + tagContents + "/>");
trace(xml.toXMLString()); // traces <elem att="value"/>

XML Namespaces:

Setting a default namespace - both parent and child get into the same namespace:

<xml>
  <parent xmlns="http://www.example.com/uri/">
    <child />
  </parent>
</xml>

Using prefix for namespaces - in this example only child element is in the namespace because only that node is using the ns prefix:

<xml xmlns:ns="http://www.example.com/uri/">
  <parent>
    <ns:child />
  </parent>
</xml>

Using Namespace instance (has 2 properties: uri & prefix):

var xml:XML =<xml xmlns:xpl="http://www.example.com/uri/"> <text>Hello World</text> <xpl:text>Hello Namespace</xpl:text> </xml>;
var xplNs:Namespace = new Namespace("http://www.example.com/uri/");
// same uri as xpl namespace
trace(xml.text);
// traces "Hello World"
trace(xml.xplNs::text);
// traces "Hello Namespace". Note the use of "::" operator
trace(xml.children().(name().localName == "text")); // traces both, note the use of localName property.

method namespace() - returns a single Namespace instance that represents the Namespace of that XML node.
method namespaceDeclarations() - returns a list of all the namespaces defined within the XML element - the default namespace (if exists) and all namespaces with their defined prefix

 

Scenes --------------------

In FlashCS3 press SHIFT-F2 to open the "scenes" window where you can switchadd new scenes, make duplicate scenes, rename a scene (double-click), change order of scenes. Note: frames are numbered consecutively through scenes. For example, if a document contains two scenes with ten frames each, the frames in Scene 2 are numbered 11–20.

In actionscript 3.0 we have array "scenes" and assoc. array "labels":

trace(scenes[0].name);
trace(scenes[0].numFrames);
trace(scenes[0].labels[0].name);
trace(scenes[0].labels[0].frame);
trace("The main movie has " + scenes.length + " scenes.");
trace("The current scene is '" + currentScene.name + "'.");
trace("It has " + currentScene.numFrames + " frame(s),");
trace(" and " + currentScene.labels.length + " label(s). ");
trace("The second scene's first label is '" + scenes[1].labels[0].name + "',");
trace(" which is in frame " + scenes[1].labels[0].frame + ".");
trace("Movie clip 'mc' has " + mc.currentLabels.length + " labels.");
trace("Its last label is '" + mc.currentLabels.pop().name + "'.");
trace(isFrameLabel("mylabel", mc));
// check if a frame label exists

Embedding swf into html --------------------

Minimum minimum code:

<object width="550" height="400">
<param name="movie" value="somefilename.swf">
<embed src="somefilename.swf" width="550" height="400">
</embed>
</object>

Things to add:

Better way:

See also (google for how to embed swf into html):

 

mxmlc compiler --------------------

When working on a big project with a lot of people it is getting inconvenient to use a .fla file as the main project. Instead developers prefer to use .as or .mxml files - and compile projects using batch files and free mxmlc compiler which comes with the free Flex SDK. You don't have to buy expensive IDE - you can use any text editor you like, - or some free IDE, for example - http://www.flashdevelop.org/community/ .

The compile command may look something like this:

"c:\path\to\flexSDK\bin\mxmlc.exe" -load-config+=C:\projects\myproject\src\obj\MyOutConfig.xml
-debug=true -benchmark=false -o C:\path\to\output\myfile.swf

Here is a great tutorial on how to compile from command line:
http://www.senocular.com/flash/tutorials/as3withmxmlc/

And here is an example for Linux:
http://asantoso.wordpress.com/2008/05/18/flex-3-sdk-command-line-development-with-example-on-linux/

Here is how to compile for Adobe AIR:
http://help.adobe.com/en_US/AIR/1.1/devappsflex/WS5b3ccc516d4fbf351e63e3d118666ade46-7fa1.html


Classpath ------------------------------

Classpath

Flash searches for libraries under directories listed in classpath. You can edit this list from your development tool, for example:

If you use a stand-alone compiler, you can provide (class)path information in the command line using options:

You can add options into the main flex-config.xml file in the frameworks subdirectory.
Or you can create your own config file - and load it using option -load-config
Or you can create your own custom batch file, for example:

REM compile.bat
@ECHO off
SET mxmlcPath="C:\flex_sdk_3\bin\mxmlc.exe"
SET opts=-benchmark=true -creator="YourName"
IF EXIST "%~dp0%~n1.swf" (DEL "%~dp1%~n1.swf")
ECHO on
%mxmlcPath% %opts% -file-specs %1
@ECHO off
IF EXIST "%~dp0%~n1.swf" (CALL "%~dp1%~n1.swf") ELSE (PAUSE)

Note about batch-syntax macros:

"%~dp0" - the path to the directory containing the batch file.
"%~n1" - the filename without the extension from the first parameter (%1).

Note: you can invoke compilation by dragging-dropping the .as file onto the .bat file
Or you can run from the prompt: compile.bat HelloWorld.as
Once the .swf file is created - you can invoke it by double-clicking on it, or by invoking it from the prompt: HelloWorld.swf.

Avery good tutorial is here:http://www.senocular.com/flash/tutorials/as3withmxmlc/

To get command-line options (on DOS prompt) run this command: mxmlc.exe -help list advanced options

On unix when you calling the mxmlc executable - it is actually a script which invokes java - something like this:

java -jar "/path/to/flex/lib/mxmlc.jar" -flexlib "/path/to/flex/frameworks/" MyApp.as

To further simplify your life you can write a simple shell script - like described here:
http://www.mikechambers.com/blog/2005/12/22/compiling-actionscript-3-and-mxml-on-mac-and-linux/

converting mxml to as: --------------------

It is inconvenient to write MXML files by hand - as it is inconvenient to write HTML by hand. But you don't have to, because there are WYSIWYG tools which will generate HTML or MXML for you - like Dreamweaver for HTML, or Flex Builder's design mode for MXML.

You can completely exclude MXML and write everything in .as files. See discussion here: http://www.kirupa.com/forum/showthread.php?t=269107 .

Reusable pieces of code can be precompiled as SWF or SWC files.

When you compile mxml application, mxmlc compiler first converts it into actionscript source - and then compiles. To see the intermediary ActionScript files that Flex generates, add the -keep-generated-actionscript option to your mxmlc command. But this process creates too many files - the result is far from optimal. For example, if you create a simple hello1.mxml application like this:

<?xml version="1.0"?>
   <Application xmlns="http://www.adobe.com/2006/mxml">
 <Label text="Hello, world!" />
 </Application>

and compile it like this:

C:\flex_sdk_3\bin\mxmlc.exe -keep-generated-actionscript hello1.mxml

then a subdirectory called "generated" will be created with 38 actionscript files in it. And the SWF file will have size 153 KBytes

If you compile the equivalent actionscript:

package {
 import flash.display.Sprite;
 import flash.text.TextField;
 
 public class HelloWorld extends Sprite {
 
   public function HelloWorld() {
     var display_txt:TextField = new TextField();
     display_txt.text = "Hello World!";
     addChild(display_txt);
   } //func
 }  // class
} // package

then "generated/*.as" files are NOT created, and the size of the SWF file is only 627 bytes (yes, less than 1 KByte, i.e 200 times smaller than when using mxml source).

Note: if you want to convert manually:

Having everything in "as" files is attractive (and you can make resulting swf files much smaller). But on the other hand, it is relatively easy to maintain mxml files in Adobe Flex Builder because you have the convenience of using GUI WYSIWYG editor. I guess you can use either approach depending on the task.

 

Flash Games --------------------

 

Miscellaneous ------------------------------

Cool widgets, sound spectrum, etc.

 

--------------------

--------------------

--------------------

--------------------