Learn HaxeFlixel from Scratch (pt. 1): The Display List and Program Entry
And thus begins my foray into learning a new language with which to program games and mobile apps. I’ve always used FreeBASIC to fiddle with desktop games in the past, but I do all of my development on OS X these days and would love to target multiple platforms for whatever I come up with. FreeBASIC doesn’t fit the bill, but Haxe seems like a strong alternate contender… and lo and behold, there is a Haxe port of the Flash game library, Flixel, appropriately dubbed HaxeFlixel.
This blog post will be the first in a series of self-educational blog posts as I teach myself not just HaxeFlixel but Haxe and not just Haxe but ActionScript programming in general. I’m truly starting from scratch here, interpreted as “from nothing” as opposed to “from that awesome GUI based programming language for kids made by MIT.” If you’re following along, you’ll need to grab the full stack of Haxe + OpenFL + HaxeFlixel as described in the project’s Getting Started guide.
My earliest attempts to understand how HaxeFlixel worked were thwarted by my lack of general understanding of how ActionScript itself works. I saw classes being tossed around like Stage, Sprite, Event, and more with no real concept for what the program would look like from a high level. So, armed with my trusty IDE and command line grep, I started digging. And digging. And digging.
Apparently ActionScript (and by extension Haxe) programming involves classes upon classes upon classes. It’s quite common to start in a class 6 steps removed from its parent class in the hierarchy (where it typically terminates in an EventDispatcher, i.e. a class that can listen for and react to events – very handy). This makes things quite daunting, to be honest, but it gets more manageable as you start to piece together a picture of the main class families in use.
My first “aha” moment came when I finally stumbled upon an ActionScript (hereafter AS) concept known as the display list. This is basically the hierarchy of objects used in an AS / Haxe program to manage all application objects / logic / display:
It all starts with that top level Stage object and descends from there through the instance of your application’s “Main” class to the various display objects and containers used to actually show stuff to users / players.
Building on this bit of knowledge, we can actually tease out how a Haxe program gets going by examining the Main.hx generated when you create a new HaxeFlixel project (see the Hello World tutorial for an example, specifically the bit introducing “haxelib run flixel”). Stepping through the code, I see the following things happening:
- The Main.hx file contains the program’s entry point, the static function main(). This function simply adds an instance of our Main class to the root object container. (It does this using Lib.current, which appears to be a MovieClip object, so I’m not sure how Lib.current sits in relation to the root Stage. A worry for another day.) Note that our Main class is a child of Sprite, which can ultimately function as a Display Object or a Display Object Container in our hierarchy.
- Creating the new Main object involves setup through its parent constructors (done using super() in Haxe) and then a quick check to see if it has been added to the program’s global Stage object yet. If so, then we directly invoke Main’s init() function. If not, we add an EventListener to the Main object (because Sprites are ultimately children of EventDispatcher) that invokes init() once it’s been added to the Stage. This use of event listeners seems quite common and analogous to jQuery’s .ready() – i.e. wait until we’re sure everything’s in place before doing anything. Bonus reading in this Republic of Code event listener tutorial I found.
- init() removes that listener if it was added and then invokes initialize() to set the program’s alignment and scaling mode. I’ll have to research those later.
- Next, init() creates the actual FlxGame object (itself a child of the Sprite class), the heart and soul of a HaxeFlixel game. It adds this object as a child of the Main object.
- Finally, if the program is being compiled to C++ or neko (a language with a virtual machine that we can use for testing on OS X thanks to openfl), a simple keyboard event listener is added that exits the program if the escape key is pressed.
- The constructor of the program’s FlxGame object is primarily responsible for determining the dimensions and scale of the game and then invoking its parent’s constructor to set everything up, including pointing to the initial “FlxState” of the game. A State is comparable to a “view” of the game and may correspond to a menu or a game screen.
- The next post in this series will dig into what happens when the constructor of our program class’s parent FlxGame class executes.
That’s about all I can manage for tonight. I’ll keep trucking through learning the nature and structure of HaxeFlixel games and try to point out any tips I pick up along the way. HaxeFlixel still comes across to me as a work in progress, but it’s an open source project hosted on GitHub (whose community portal is Drupal powered, yay!), which just screams to me “fork me and fix things.”
I intend to oblige.