TwelvestoneFlash

haXe flash quick start


Sign in

  • Waiting for Godot ( 720 k posts )
    Just conversation.
  • Thunder Dome ( 23 k posts )
    Photoshop Tennis and Collabs.
  • Photography ( 4.8 k posts )
    For all you shutterbugs, sh...
  • Flash ( 18 k posts )
    ActionScripting to tweens, ...
  • Front End ( 5.8 k posts )
    general front end design an...
  • Back End ( 9.6 k posts )
    serverside scripting, progr...
  • Projects and Theory ( 12 k posts )
    This forum is for discussio...
  • FAQ ( 269 posts )
    All those nagging questions...
  • Design ( 17 k posts )
    graphics & all aspects of g...
  • Purgatory ( 3.6 k posts )
    12stone Jail, feel free to ...
JLM
 
2009-01-25

Introduction to haXe for flash ASM-2 - A guide for twelvestone


Copyright 2009 Justin L Mills, first section and draft WIP.

I suggest anyone who does not know anything about haxe visithttp://www.haxe.org or buy 'Proffessional HaXe and Neko' to learn more, I am only giving a brief covering of haxe you will have to research areas further.

I have assumed AS2 knowledge with very limited exposure to AS3.

This tutorial is centered about flash9+ and haXe use and is very limited to my main area of interest. I use a mac and textmate, but you can use what you want (platform/text editor combination), the main haxe site should get you set up, so assuming your set, lets get started.

Compile file structure


HaXe does not replace the Flash IDE, haXe is like actionscript, its not a graphics tool. Don't worry you do not need to throw away your flash IDE it can work along side haXe, unless your obsessed with open-source for the sake of it. I live in the real world where inkscape and gimp will not be replacing Adobes design suite.

haXe is a compiled by the command line, this is kind of a shock if your used to just using flash IDE, but normally you can find tools to help you avoid terminal to do this though yon need to store the compile instruction in an *.hxml file. For a flash 9 project a typical file might contain the plain text below:

-swf tut1.swf
-swf-version 9
-main Tut1
-swf-header 800:600:31:ffffff

Options for compiling can be quite complex, but for our needs lets just consider the above sample that contains what we need.

1) The first line defines the name of the swf we are creating, "tut1.swf".

2) The second line is the flash target player ( haXe can compile to the latest flash player, 10 and older versions ), haXe code can contain special 'if.. else' statements that the compiler uses to compile to different platforms, pre flash 9 is different in some of the classes used, so if we want to compile code for flash 8 and flash 9 our classes would need compiler 'if' switches. haXe has core classes of code that are designed to be cross platform, and also platform specific classes that wrap the platforms classes. We are just considering flash 9 player compile here not more complex compiles.

3) This line is defining our boot or main class, this will be a file named Tut1.hx although it could be named something else notice we do not include the file extension.

4) The last line in our compiler directive file defines the general swf properties commonly known as the header and stored at the beginning of a compiled swf. In our case we are creating a 800 pixels wide, by 600 pixels tall at 31 frames per second with a white background defined in hex, FFFFFF.

Classes and Main Class Structure


Example of a generic haXe class might be:

// you can not use * in imports you need to declare them all!
import flash.display.MovieClip;

class MyClass extends MovieClip
{

    private var aVariable: Int

    // Constructor
    public function new( val: Int ):Void
    {

        aVariable  = val;
        var aFloat: Float = cast( method1, Float ); // 'cast' not really needed here.
        super();//needed if Inheriting          

    }

    private function method1( val: Int ): Float
    {
        var aNumber: Float = Std.float( val ); // Float is the haXe of Number
        return aNumber;
    }

    /*
      properties are defined by a getter and setter and a fancy variable  
      although support for instance['_property'] array dynamic access construction is limited and unlike actionscript is done instead by using
      Reflection, where possible stick with a get and a set or a simple variable as they work with the Reflect class        */
    public var _property( gePropertyl: Int, setProperty:Int ): int

    // not the setter has to have a return to allow     instance._propery++
    private function setProperty( prop: Int ):Int
    {
        aVariable = prop;
    }
    private function getProperty():Int
    {
        return aVariable
    }

}

Please study the class it should look fairly similar to actionscript. Now this is a generic class example, but our main swf class needs to be a bit different, it needs a static method to boot the Movie into starting called 'main'. Static methods are methods that are called on a Class rather than an instance of the class, this main static method creates an instance of you main class in our case below, 'MyMainClass'

// required to allow you to put things on to the flash stage
import flash.Lib;

class MyMainClass
{

    private var _stage: MovieClip

    public function new( ):Void
    {
        _stage = Lib.current;       
    }   

    public static function main( val: Int ): Float
    {
        new MyMainClass();
    }

}

Some documentation suggests Lib.current.stage rather than what I have, but when loading this swf into another I have found this to be the best basic structure, although I may change my opinion as I learn more.

Adding to the Stage and displayobject AS3 properties


Like as3, haXe has addChlid to put textfields and movieclips on stage and they are created like normal classes before hand. Flash 9 now has a Sprite class, essentially its the same as MovieClip, you can use onEnterFrame on a Sprite but it does not have a timeline and Sprites are not Dynamic. That is to say in AS3 you can add properties in an cbject manor to MovieClips, but not Sprites. Sprites are lighter than MovieClips, I recommend you use MovieClip's everywhere to start with, since the flashplayer does not treat them as the same type although they are often, if only in our mind.

So in haXe (AS3) we create and add items to the stage

var mc: MovieClip = new MovieClip();
_stage.addChild( mc );
mc.x = 200;
mc.y = 200;

var tx: TextField = new TextField();
_stage.addChild( tx );
tx.x = 200;
tx.y = 200;
tx.text = "test";

addChild places at the next avaliable depth. //TODO: add more here... Notice haXe (AS3) flash visual elements properties have all lost the '_' underscores, also properties that are percentages or fraction are all now fractions, so scaleX and alpha both are defined as ranges 0 to 1.

Built in and user created Classes


All classes used in haXe are documented http://www.haxe.org/api/

Additional generic classes are actively shared in the haXe community, they can be uploaded to http://lib.haxe.org/ and also downloaded

To get a user class you need to install haxeLib and then you can open terminal and use it to get classes you need, for instance if you want to create 3D flash then you could download sandy. haxeLib install sandy

More details on haxeLib can be foundhttp://www.haxe.org/doc/haxelib/using_haxelib

On a tiger mac these classes are created somewhere like Machintosh HD/usr/lib/haxe/lib

it is often a hidden/restricted area of your computer and should be found by the compiler if you use classes in a project, for instance facebook port can be installed haxeLib install facebookx

and then imported into your main class import facebookx.FacebookX;

Events Custom and Built in


AS3 has simplified events in flash, haXe being cross platform does not commit to an Event model, but since most events are generated by the flashplayer it is worth using compatible code for our custom events. Any class that is in the Inheritance chain of EventDispatcher can have its instances dispatchEvents that other classes' instances can listen to. When an event happens we dispatch that event as an Event instance. There is no standard Event class structure as there are more possibilities in haxe, for instance enum and typeDef that can be used in systems, I am currently using an Event model that is similar to the custom events described by Moock in his actionscript book, I have not included a toString (used in trace functionality), and I have not tested it extensively but have researched and consulted another haXe user, if you are integrating with haXe javascript maybe a different structure might be used. I will start with a custom event structure, don't worry if its a bit complex we will be coming back to simpler basic events such as button and onEnterFrame.

Custom event class, an instance of which is passed by EventDispatcher-able instance when you want to signify an event, I am not a great expert, and I treat this as a template structure for my custom events.

import flash.events.Event;

// inherit from flashes basic event class
class SimpleLoadEvent extends Event
{
    // These are the event types we listen for.
        public static inline var PROGRESS:                 String = "simpleloading_progress";
        public static inline var PRESSED:                    String = "simpleloading_pressed";
        public static inline var VISUALLOADED:        String = "simpleloading_visuallyloaded";
        public static inline var LIBRARY_LOADED:   String = "simpleloading_library_loaded";
        public static inline var COMPLETED:               String = "simpleloading_complete";

    // this is often optional parameters that we can shove info into, I have kept mine simple, Dynamic is like Object in flash and really means what ever type you need
              // notice these only have public getters as they can only be set in the constructor when the event is created 
    public var ref(    default, null ):           Dynamic;
        public var data( default, null ):      Dynamic;

    // ? = optional
        public function new( 
                                            type:                    String, 
                                            ?bubbles:           Null    <Bool>, 
                                            ?cancelable:      Null    <Bool>, 
                                            ?eventRef:          Null    <Dynamic>,
                                            ?eventData:        Null    <Dynamic>
                                    )
        {
                if ( bubbles    == null ) bubbles       = false;
                if ( cancelable == null ) cancelable    = false;

                super( type, bubbles, cancelable );

                ref         = eventRef;
                data      = eventData; 
        }

        override public function clone():Event
     {
                return new SimpleLoadEvent( 
                                    type, 
                                    bubbles, 
                                    cancelable, 
                                    ref, 
                                    data 
                                );   
        }
}

To dispatch or create an event of say LIBRARY_LOADED we may put code like

import flash.events.EventDispatcher;
import flash.events.Event;
import SimpleLoadEvent;

class MyDispatchingClass extends EventDispatcher
{
    public function new():Void
    {

    }

            public function init():Void
        dispatchEvent( new SimpleLoadEvent(   
                                                SimpleLoadEvent.LIBRARY_LOADED, 
                                                true,
                                                 false,
                                                'test',
                                                'test'
                                                )
                        );
    }
}

in our class that creates the event.
Typically when using a class we create an instance set listeners and then initialize it (once listeners are listening!).

import flash.events.EventDispatcher;
import flash.events.Event;
import SimpleLoadEvent;
import MyDispatchingClass;

class MyListeningClass extends EventDispatcher
{

    public function new():Void
    {
        var myInstance: MyDispatchingClass = new MyDispatchingClass();
        myInstance.addEventListener( SimpleLoadEvent.LIBRARY_LOADED, libLoaded );;

        // callback is really useful similar in concept to classes like DelegateWithArgs is in AS2
        myInstance.addEventListener( SimpleLoadEvent.COMPLETED, calback( created, 'extraInfo' ) )           

        myInstance.init();
    }

    private function libLoaded( e: SimpleLoadEvent ):Void
    {
        // do something with e.ref or e.data?
    }

    private function created( str: String, e: SimpleLoadEvent ):Void
    {
        // do something with str
    }

}

In the example I have the dspatcher class inherited from EventDispatcher, but often we can inherit from MovieClip or similar instead. So lets get back to basic flash events.

We can create a basic MovieClip button and listen to it, also is code for creating some code graphics.

import flash.events.EventDispatcher;
import flash.events.MouseEvent;
import flash.Lib;
import flash.display.MovieClip;
import flash.text.TextField;

class MyMainClass
{

    private var _stage: MovieClip

    public function new( ):Void
    {
        _stage = Lib.current;   
        var mc: MovieClip = new MovieClip();
                mc.x = 100;
        mc.y    = 100;  

        // draw rectangle
        mc.graphics.beginFill( 0xFF0000,  1);// red 100%
                mc.graphics.lineStyle( 0, 0x00FF00, 1  );// blue border 100%
                mc.graphics.drawRect( 0, 0, 200, 100  );// 200x100 rectangle
                mc.graphics.endFill();  
        mc.addEventListener(  MouseEvent.MOUSE_DOWN, clicked );

        // allow cursor to act as hand (and to allow flash rollover label frames)
        mc.buttonMode     = true;
                mc.mouseChildren  = false;

        _stage.addChild( mc );

    }   

    // must have e 
    private function clicked( e: MouseEvent ):Void
    {
        var tx: TextField = new TextField();
        tx.text = 'clicked';
        _stage.addChild( tx );  
    }

    public static function main( val: Int ): Float
    {
        new MyMainClass();
    }

}

If your used to AS3 then this looks fairly similar k. For onEnterFrame we use similar structures ie

mc.addEventListener( Event.ENTER_FRAME, rotate );

I will leave you to work it out fully as most of you have seen some or lots of as3. So far haXe seems fairly like AS3 and not too far from AS2, now let look at some differences and an alternative to onEnterFrame.

Timer Class


The Timer class is a cross platform class it is implemented it the haxe library indicating that across platforms its internal implementation is very different, but it is good in that code using it can potentially be platform independent the holy grail and a main point of haxe. I think this example should be enough to cover Timer class use...

private var _counter: Int;
private var _step: Int;
private function createTimer():Void
    {   
    // cycle time 0.1ms
    _step = 100;
            var timer = new haxe.Timer( _step );
            _counter = 0;
            timer.run = timerRun;
    }
    private function timerRun():Void
{
            _counter += _step;
    // wait 10 seconds
            if( _counter > 10000 )
            {
                _timer.stop(); 
        // timer finish  
        }
            else
            { 
        // timer cycle do your enterframe stuff here
            }        
    }

Bool


Bool is flashes Boolean.

Reflection on [ ] access of Objects


Actionscript uses array notation heavily, haXe instead uses Reflection, to be honest from my perspective its a pain, but it probably helps cross platform support.
For example looping through an Object

    var o: Dynamic = { a:'a',b:'b',c:'c'};
    for( all in Reflect.fields( o ) )
    {
        trace( Reflect.field( o, all ) ) ;
    }

Iterators, Loops, Lists and Lambda


Arrays have slightly different methods, 'add' is used in place of push. Looping through arrays is a common theme in flash, but in haXe we often loop through Lists, a lighter object that can only be accessed via an iterator, I urge you to try to replace your Arrays with lists. To understand Lists you need to understand how haXe does loops. Looping in haXe is generally different from actionscript.

// haxe has a more complex type system where we are more sure of types in types.

        var list<String> = new List( );

// we can loop tthrough an array with an iterator to populate a list
for( i in [ 'A', 'B', 'C' ].iterator() )
        { 
            list.add( i );
}

// once in a list we can access elements in a loop
    for( i in list.iterator() )
    {
        trace( i );
    }

but more interestingly we can use map to create a new list based on a functional mapping of the current list. Mappings function are declared by there input and output types.

var addUnderScore: String - > String;

So use

addUnderScore = function( str: String ):String{ return str+'_' };
var newList: List = origList.map( addUnderScore );

In haxe we can also use the Lambda class with map ( and mapi ) which seem a bit simpler since we don't seem to need that funny var declaration, look one line!

var newList: List = Lambada.map( origList, function( str: String ):String{ return str+'_' } );

It may not seem that useful, but while we can't access a list where we want, we can apply changes to the list without creating a for loop.

origList = Lambada.map( origList, function( str: String ):String{ return str+'_' } );

Type


The Type class is very useful when loading a swf in, as it allows us to resolve classes in a more logical manor than in AS3. Loading in AS3 is rather messy so for the moment I will not go into details. The important aspect is that to use symbols from a movie that has loaded as if they are in our local library, we need to specify the LoaderContext's ApplicationDomain to be the main movies current ApplicationDomain when loading the movie.

So assuming we have loaded in a movie to our current ApplicationDomain ( there are several haxe loaders, that help you achieve this), then we can create textfields with the embedded font without even registering the font..

public static function createTextField( mcLinkage: String, txtFieldInstance: String ): TextField
{

    var mc:     MovieClip = cast( Type.createInstance( Type.resolveClass( mcLinkage ), [] ), MovieClip);
    var txt:    TextField = cast( mc.getChildByName( txtFieldInstance ), TextField );
    mc = null;

    return txt;

} 

In AS3 we can no longer rely on dot syntax to traverse up and down MovieClip structures seamlessly and often we end up using methods such as getChildByName.

JLM
 
2009-01-25

I will read through it at another time and improve, I realise there are quite a few typos. Might be good if its sticky?

scudsucker
 
2009-01-26

That is really cool, thanks very much.

Storm
 
2009-01-26

sticky!! very cool JLM. Thanks for writing all of that.

Of note, I would add you can use FlashDevelop as an IDE with Haxe for those people scared (ME) of command line compiling. FD sets up a Haxe project nicely.

mystic_juju
 
2009-01-27

also - PureMVC (http://www.puremvc.org) has a port for haxe, so it's immediately stickable in a nice framework.

JLM
 
2009-01-27

Some rough code I have been experimenting with should be helpfull in loading swf assets at runtime.

haxe loading test

source

JLM
 
2009-01-27

mystic_juju

do you use puremvc?

;j

mystic_juju
 
2009-01-28

yeah - needed to change a few lines, but it works now and is definitely worth it, in my opinion.

JLM
 
2009-01-29

it?

mystic_juju
 
2009-01-29

Well when I used the framework, there were some errors when I tried to compile my file - as far as I remember, the errors had mostly to do with using a variable without having initialized it, so I set some of these to Dynamic by default, and there were a few minor other things. These were errors in the PureMVC port to haXe, so I had to modify that. Once I did that, things would compile fine. Now it (the framework) works fine without throwing any errors.

Sorry, you must be a member to post to a conversation. Either log in or sign up to get involved.
TwelvestoneFlash

haXe flash quick start