LevSelector.com |
Actionscript (page under construction - still you may find it very useful)
On This Page | Other Pages | ||
- intro |
- function reference |
- threads |
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, Copy-paste the following into the editor window: // ------------------------------------------------------- var v1 = "mama"; trace(v1); // typed variables var v3:Number = 100 + 10.5; trace(v3 + 30); var b1:Boolean = true; trace(b1); // true Now press Ctrl-S to save the file. |
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 function my1(el:*, i:int, a:Array):void {
trace("" + el + ", " + i);
} a.push("v1","v2"); for (var i:int = 0; i < a.length; i++) {trace(i + ": " + a[i]); } a.splice(start,delete_count); // deleting var s:String = a.join("|"); // default separator is a comma 2-dim array: var a:Array = new Array(); Copying array: var a1:Array = [1,2,3]; 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. var a:Array = ["a","b"];
|
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 General form: Array.sort(compareFunction, sortOptions); where: 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.reverse() Reverses the array in place
|
Hashes ------------------------------
Associative array (hash): var h:Object = new Object(); 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 for each (var vv:* in h) { // for..each iterates through values (not keys) h = {}; // empty the hash var h:Object = {}; or var h:Object = { Note: if you want to keep object refs as keys, you should use Dictionary instead of an Object: var arr:Array = ["abc","def"]; |
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: |
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 = s1 + s2; // concatenating Convert number n to string s: s = n; // error Regular expressions - similar to Perl (understands standard modifiers (g,i,x,s,m), parentheses, etc.). http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/RegExp.html var p:RegExp = /(gold).+(kruka)/is; |
Math ------------------------------
Math class: Constants: Math.PI, Math.E |
Dates ------------------------------
Working with dates: Final class Date: http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/Date.html var mydate:Date = new Date(); // now Examples of properties: mydate.time - milliseconds since midnight January 1, 1970, universal time var time:int = mydate.time; Examples of methods: mydate.getDate(); // returns day of the month |
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 { //------------------------------------------------------------- there is only one public method to interact with, that is dateDiff. var now:Date = new Date(); |
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;} 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:
var v1:Number = 1; function test(v1:Number, v2:String, v3:Array):String { var v4:String = test(v1,v2,v3); Output: before: 1, A, 1,2,3 |
------------------------------------------------------------------------------------------
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, function f1(...a):void {trace(a.length +": "+ a);} |
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 // In Animal_impl.as // In Dog.as // In Cat.as If you ask the dog if he's an Animal - he'll surely respond that he is: var dog:Dog = new Dog; |
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" ); stream.close(); // Clean up |
Working with directories:
var dir:File = File.desktopDirectory.resolve( "path/to/dir" ); private function handleDirectoryListing( event:FileListEvent ):void
{ |
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 v1:Function = new_greeting("person1"); v1(); // Hello person1 -- 1 |
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 |
| |
\ MorphShape |
\ StaticText |
||||||||||||
|
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 // Remove frame 1's script |
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 var loader:Loader = new Loader(); function assetLoaded(e:Event):void{ |
Yet another method of copying is to use Bitmap object:
public function copyBitmap(o1: DisplayObject) : Bitmap
{ |
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; |
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
|
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 = "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 |
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):
|
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: |
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 |
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)) |
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 |
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
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 |
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.
--------------------
--------------------
--------------------
--------------------