AS2 << >> Haxe/flash comparison

AS2 << >> Haxe/flash comparison

or "How to port code from mtasc -strict to Haxe."

Accessing Classes

Toplevel Flash classes have been moved in the "flash" package, in order to separate Flash-specific classes from Javascript or Server-specific ones. To use these toplevel classes in Haxe, you need to use an import statement, or preface their names with "flash."

Note: There are some Flash 8 classes which you should already be used to referencing this way (e.g. flash.display.BitmapData).

Here are the classes that you will have to import to use.

flash.Accessibility;
flash.Camera;
flash.Color;
flash.Key;
flash.LoadVars;
flash.LocalConnection;
flash.Microphone;
flash.Mouse;
flash.MovieClip;
flash.MovieClipLoader;
flash.PrintJob;
flash.Selection;
flash.SharedObject;
flash.Sound;
flash.Stage;
flash.System;
flash.TextField;
flash.TextFormat;
flash.TextSnapshot;
flash.Video;
flash.system.Capabilities; //note the capitalization
flash.system.Security; //note the capitalization

Flash Types

The following Flash types are slightly different in Haxe.

  • Array
  • Boolean
  • Function
  • Number
  • Object

Array

Arrays are strictly typed in Haxe. You need to specify the type of the array content by using < and >.

//ActionScript
var a:Array=["a","b","c"];

//haxe
var a:Array<String>=["a","b","c"];

Boolean

Booleans are implemented in Haxe with an enum called Bool.

//ActionScript
var b:Boolean=true;

//Haxe
var b:Bool=true;

Booleans are not objects in Haxe, they are abstract values.

Function

There is no function class, but there is a function type, which Haxe will infer for you.

//ActionScript
var fun:Function = function (){ ... }

//Haxe
var fun = function (){ ... }

You can also specify the function type explicitly :

var fun : Void -> Bool = function() { return false; }

Number

Numbers in Haxe are either Float (decimal point numbers) or Int (integers).

//ActionScript
var i:Number=42;
var j:Number=1.618034;

//Haxe
var i:Int=42;
var j:Float=1.618034;

Int and Float types are compiled to the more suitable primitive types depending on the plaform. Do not assume that they are objects.

Object

In Haxe, use Dynamic instead of Object when you want to signify that a variable can be of any type.

//ActionScript
var obj1:Object=7;
var obj2:Object="a string";

//Haxe
var obj1:Dynamic=7;
var obj2:Dynamic="a string";

Dynamic is actually like the ActionScript2 "untyped" variable. You can use it in any way you want.

Expressions

Some expressions have differences between ActionScript and Haxe.
In particular, control structures in ActionScript are statements, and do not return a value. In Haxe, control structures are expressions, and return the value of their last evaluated subexpression.

Control structures include: while, do while, switch, if, if else

break Statements

In Haxe, "break;" statements are not recognized inside switch statements, but are implied before each case/default statement.
This will prevent a very common error (leaving them out).

//ActionScript
switch(val){
    case val:
        doSomething();
    break;
    default:
        doSomethingElse();
    break;
}

//Haxe
switch(val){
    case val:
        doSomething();
    default:
        doSomethingElse();
}

(As a side effect, some more advanced uses of the switch statement will have to be restructured.)

for loops

The most common for loop has a simpler syntax in haxe.

//ActionScript
for(var i=0;i<num;i++){
    doSomething();
}

//Haxe
for(i in 0...num){ //note: no var
    doSomething();
}

Other, less common for loops can be implemented using Iterators, or expanded to while loop syntax.
var i=0;
while(i<num){
    ...
    i++;
}

for in loops

In Haxe, an array is iterable, meaning you can loop through its members directly with a for..in loop.

//ActionScript
for(var i in arr){
    //i is the index into arr
    doSomething(arr[i]);
}

//Haxe
for(x in arr){
    //x is the next member of arr
    doSomething(x);
}

To get the array indexes instead, use arr.indexes, or an int iterator.
//Haxe
for(i in 0...arr.length)
    doSomethingTricky(arr[i],i*2+3);

By contrast, objects in Haxe are not iterable. So, while in ActionScript you can do this:

//ActionScript
var obj:Object;
...
for(var i in obj)
    trace("obj."+i+" is "+obj[i]);

In Haxe you would use a special class called Reflect to access the properties of a Dynamic object.
//Haxe
var obj:Dynamic;
...
for(i in Reflect.fields(obj))
    trace("obj."+i+" is "+Reflect.field(obj,i));

A common use of 'for in' loops in AS2 is to find all the MovieClips in a MovieClip, this is not really a good approach and in Haxe you should keep a reference to any you create and store them in an array or similar, but obviously with any timeline MovieClips this does not help. So an alternative is to loop through all the depths.
//haxe
var i: Int = _movie.getNextHighestDepth();// not supported in flash 6
var mc: Dynamic;
while( --i != -16385 )
{
   mc = _movie.getInstanceAtDepth( i );
   if( Std.is( mc, MovieClip ) )
   {
      trace( cast( mc, MovieClip )._name );
   }
}

Properties

The Reflect Haxe class is used for all manipulation of dynamic properties. It's a complete Refection API (also called introspection).

String access

//ActionScript
var prop:String="width";
if( obj[prop] == null ) {
    obj[prop]=100;
    trace(obj[prop]);
}

//Haxe
var prop:String="width";
if(Reflect.hasField(obj,prop)){
    Reflect.setField(obj,prop,100);
    trace(Reflect.field(obj,prop));
}

If the field is not found in Reflect.field, an exception will be thrown.

Delete

//ActionScript
var prop:String="width";
delete obj[prop];

//Haxe
var prop:String="width";
Reflect.deleteField(obj,prop);

arguments

In ActionScript you can use the arguments object in functions to accept optional arguments, and access a reference to the current function, or the calling function.

//ActionScript
var arr:Array=arguments;
var fun1:Function=arguments.callee;
var fun2:Function=arguments.caller;

Haxe provides a way to access these properties, but their use is not recommended since they are only available for Flash. See Haxe Magic
untyped{
arr=__arguments__;
fun=__arguments__.callee;
fun=__arguments__.caller;
num=__arguments__.length;
}

Please note that Haxe can declare functions with Optional Typed Arguments.

Classes and Instances

packages

In ActionScript, you designate the package of a class in the class definition.

class pkg.ClassName {
}

Haxe handles packages more like Java does, with a package declaration that applies to the file as a whole.
package pkg;
class ClassName {
}

See Packages and Imports

constructors

In ActionScript constructors have the same name as the class.

class Something{
    function Something(){

    }
}

In Haxe the constructor is always given the name 'new'. This way if you rename your class you don't have to rename the constructor.
class Something{
    function new(){
    }
}

naming

In ActionScript it is standard practices to begin class names with uppercase letters, and parts of the package name with lowercase letters. In Haxe this standard is enforced by the compiler.

//unusually styled ActionScript
class pkg.ClassName {
}

//Haxe
package pkg;
class ClassName {
}

prototype, etc.

ActionScript provides the prototype and constructor properties for inspecting class definitions and hierarchy.

obj.__proto__;
obj.prototype;
obj.constructor;

In Haxe you can use the Reflect API to get the object Class :
var c : Class = Reflect.getClass(obj);
trace(c.__name__);
trace(c.prototype);
...

This doesn't work with native/extern classes such as Array or flash.MovieClip for example.

instanceof and casting

//ActionScript
if(obj instanceof MovieClip){
    var mc:MovieClip= MovieClip(obj);
}

//Haxe
if(Std.is(obj, MovieClip)){
    var mc:MovieClip= cast(obj,MovieClip);
}

NOTE: Also, when inspecting primitive types, Haxe's instanceof behaves more the way you would expect than ActionScript's instanceof.

//ActionScript
trace(("hello") instanceof String); //false
trace((true) instanceof Boolean); //false
trace((5) instanceof Number); //false

//Haxe
trace(Std.is("hello", String)); //true
trace(Std.is(true, Bool)); //true
trace(Std.is(5, Int)); //true
trace(Std.is(5, Float)); //true
trace(Std.is(5.1, Int)); //false

Flash TopLevel

Some ActionScript things you may be wondering how to find in Haxe...

_root

//ActionScript
_level0;/*the global root*/
_root;  /*the global root, or in a loadMovie() swf, 
the local root (if the loaded swf sets _lockroot=true) */

//Haxe
flash.Lib._root;/*the global root (_level0)*/
flash.Lib.current;/*the root of the current swf (even in loadMovie() swfs)*/

_global

In Haxe, you can access the _global object as flash.Lib._global.

//Haxe
flash.Lib._global;

These functions are used for integrating swfs into macromedia authoring environments, they are stored inside _global :

//ActionScript
FWEndCommand()
FWJavascript()
MMEndCommand()
MMExecute()
MMSave()
profile() //Macromedia Flex Debug Tool

others

There is no top-level functions in Haxe, so all ActionScript toplevel functions are stored in objects API, see Std and Lib where most of these functions are available.

For trace, Haxe adds more information and displays the result on the screen. You can use Flash old trace instead, accessible through flash.Lib.trace.

Other changes :

   escape //Haxe: StringTools.urlEncode
   unescape //Haxe: StringTools.urlDecode
   getVersion(); //Haxe: system.Capabilities.version

Haxe does not plan to provide equivalents for these functions:

   nextScene();
   prevScene();
   loadMovieNum();
   loadVariablesNum();
   printAsBitmap();
   printNum();
   printNumAsBitmap();

Flash API

Most of the methods and properties of the Flash classes are exactly the same in Haxe. However, there are a few things that are different, either because the rules of the Haxe language required a change (for example, capitalizing the Capabilities object), or because Haxe adopted an API that can be used across platforms (for example, the Xml class instead of XMLNode).

Array Class

(coming soon)

Button Class

//ActionScript
var btn:Button;

//Haxe
var btn:MovieClip;

You don't need buttons anymore. How long have you been coding?

Date Class

(coming soon)

Function Class

The Function object's call() and apply() are replaced in Haxe by Reflect.callMethod

//ActionScript
func.apply(scopeObj,[arg1,arg2,arg3]);

//Haxe
Reflect.callMethod(scopeObj,func,[arg1,arg2,arg3]);

Math Class

Some properties of the Math class have no Haxe equivalents yet.

//ActionScript
Math.E;
Math.LN10;
Math.LN2;
Math.LOG10E;
Math.LOG2E;
Math.SQRT1_2;
Math.SQRT2;

PI is available.

Number Class

Equivalents to some usages :

Number.NaN; // Haxe: Math.NaN
Number.NEGATIVE_INFINITY; // Haxe : Math.NEGATIVE_INFINITY
Number.POSITIVE_INFINITY; // Haxe : Math.POSITIVE_INFINITY
num=Number(val); // Haxe : Std.parseInt or Std.parseFloat

Some properties of the Number class have no Haxe equivalents yet.

//ActionScript
Number.MAX_VALUE;
Number.MIN_VALUE;
num.toString(2);// binary
num.toString(36);// base 36

Object Class

Instead of Object.registerClass, you can use flash.Lib.registerClass.

The following methods of Object are not yet available in Haxe.

//ActionScript
obj.unwatch();
obj.watch();
obj.addProperty();

String Class

Because the String class is the same for all Haxe platforms, there are a few differences from the ActionScript String class.

//ActionScript
var str:String = String(val);
str.slice(0,4);

//Haxe
var str:String = Std.string(val);
//str.slice(0,4); //use substr or substring instead

XML Class

The Haxe Xml class replaces ActionScript's XMLNode class, and is available for all 3 Haxe platforms. This follow the W3C DOM recommendation.

//ActionScript
var xml:XML = new XML("<tag attr='val'></tag>");
var node:XMLNode = xml.childNodes[0];
trace(node.attributes.attr);

//Haxe
var xml:Xml = Xml.parse("<tag attr='val'></tag>");
var node:Xml = xml.firstChild();
trace(node.get("attr"));

To load external text/xml files in Haxe you must use LoadVars to get a raw string, and Xml.parse to parse it.
//Haxe
var lv=new flash.LoadVars();
lv.onData=function(str:String){
    var node:Xml=Xml.parse(str);
}
lv.load('file.xml');
version #9310, modified 2010-10-15 13:52:07 by shelby