Sunday, September 18, 2011

So I started working on a Flash game using as3isolib...

This is a long post...  So if you've only got a few minutes, by all means, come back later... If you have plenty of time, grab a cup of coffee or something and enjoy :)

So I got the idea to start tinkering with Flash and finally learn Action Script.  Since I *ONLY* run Linux, this proved to be way more difficult than it should have been, so I'm trying to document some of the pitfalls I ran across, since almost all of the documentation out there is for Flash Builder or Adobe CS5 or whatever it is.

Anyways, since I'm doing this in my freetime, I didn't want to spend any money on this, and since Adobe no longer has a version of Flash Builder for Linux, I was left with just the Flex SDK.  Luckily though, this means these instructions should work for any UNIX clone.

So I decided I'm going to work on a game with an isometric view.  Probably not the best idea to learn a new language and a new display mechanic at the same time, but oh well, I'm getting there :)

I'm using version 4.5.1 of the Flex SDK.  However, I had problems with Flash crashing when using the Flash 10 plugin, so I bumped up to Flash 11 and everything is working (note that I'm on 64bit Linux).

So once you have the SDK downloaded and extracted, you can play around with compiling/testing the examples, but that's boring, so let's do some fun stuff.

For my isometric engine, I decided to use as3isolib.  It's been around awhile, and is apparently used in a ton of Facebook games.  They provide an example of using it with Flex, but it's lame since it has all of the example embeded in an mxml file... More on that later...

So now I have all the parts and am right to start coding right?  Nope, not by a long shot!  Remember, no IDE.  But we're Linux/UNIX users, so we're used to this right? :)  But what are we going to use to build our code then?  Well, we could call mxmlc (one of the Flex compilers) from a shell script...  While that'll work, it's a total PITA.  So we're going to use ANT.

While this seems funny since ANT is typically used only for Java, but it turns out Adobe even created an ANT task that's included in the Flex SDK.  So easy peasy, but how.

Well for starters, let's look at how I setup my directory hierarchy:

  • flash
    • flexsdk
    • game
I have a directory named flash, that has two sub-directories, flexsdk and game.  Under my game directory, I have the following:
  • game
    • bin
    • build
    • lib
    • src
So if it's not clear from looking... bin will hold our output, build will hold our build stuff, lib will hold our external libraries (like as3isolib) and src will hold our source code.

The Flex SDK comes with two compilers: mxmlc and compc.  Mxmlc is used to build swf files (normal flash videos/apps) and compc is used to build swc (shared libraries).  However, Flex is designed more or less for applications and expects you to have a special mxml file that defines your UI structure and the basics of your code.  This works great for examples, but anything of a decent size and it's a mess, since as you probably guessed an mxml file is an xml file using some Adobe namespaces.  What you wouldn't have guessed is that the Action Script code you have in the mxml file, is in a <![CDATA[ block, which of course means you won't get any nifty syntax highlighting.  So long story short, we'll be using mxmlc.

So now that we know what compiler we're going to use, we need to setup our build.xml file for ANT.  So without further ado:

<?xml version="1.0" encoding="utf-8"?>
<project name="Game" basedir="../" default="swf">
<property file="./build/build.properties"/> 
<property name="appname" value="game"/> 
<property name="bin.dir" value="${basedir}/bin"/>
<property name="build.dir" value="${basedir}/build"/>
<property name="src.dir" value="${basedir}/src"/> 
<property name="manifest.uri" value="http://www.reaperworld.com/"/>
<property name="manifest.xml" value="${basedir}/build/manifest.xml"/> 
<taskdef resource="flexTasks.tasks"
classpath="${FLEX_HOME}/ant/lib/flexTasks.jar"/> 
<target name="clean">
<mkdir dir="${bin.dir}"/>
<delete includeemptydirs="true">
<fileset dir="${bin.dir}"
includes="**/*"/>
</delete>
</target> 
<target name="swf" depends="clean">
<mxmlc output="${bin.dir}/${appname}.swf"
      file="${src.dir}/game.mxml"
      accessible="true"
>
<load-config filename="${FLEX_HOME}/frameworks/flex-config.xml"/>
<source-path path-element="${FLEX_HOME}/frameworks"/>
<source-path path-element="${src.dir}"/>
<compiler.include-libraries dir="${basedir}/lib" append="true">
<include name="as3isolib.v1.core.swc"/>
</compiler.include-libraries>
</mxmlc>
</target>
</project>
If you're familiar with ANT, you'll notice that this is a pretty straight forward build.xml.  If you're not familiar with ANT, just use what's here and google for some better ANT tutorials ;).  A few things to note are the taskdef and mxmlc elements.  The taskdef element points ANT to the Jar that holds the Flex ANT tasks, and the mxmlc element is where we're doing are actual building.

The other line we want to pay close attention to is <property file="./build/build.properties"/>.  This line includes our properties file that is specific to the machine we're currently running on.  Mine contains the following;
FLEX_HOME = /home/grim/programming/flash/flexsdk
 The Flex ANT tasks require FLEX_HOME to be set, so we re-use it throughout the build.xml.  In this case, I have it extracted to /home/grim/programming/flash/flexsdk.  So I point it to that.

Now that we have the build setup, let's start coding...  But if you haven't done so yet, copy your downloaded as3isolib .swc file into your lib/ directory.

Since mxmlc won't create a .swf file without a .mxml file, let's get that created.  As I mentioned earlier, as3isolib provides a tutorial for using it with Flex, but it's VERY basic.  What we're going to do here is have the bare minimums in our .mxml file, and handle everything else in included action script sources.  So here is my game.mxml:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
                layout="absolute"
                creationComplete="init()"
                width="100%"
                height="100%"
>
<mx:Script>
<![CDATA[
private function init():void {
// create the game and add it to our main view
this.addChild(new Game());
}
]]>
</mx:Script>
</mx:Application>
This is obviously very simplified, but believe it or not, it took me over a week of tinkering on and off to get it to this point.  Long story short, the as3isolib scene and view classes are sub-classes of Sprite, but you can only add a sub-class of UIComponent into a flex application instance.  So, as you may have guessed, the Game class is a sub-class of UIComponent.

Anyways, let's write our Game class so we can actually compile, test, and really start coding ;)  Like Java, our public Classes need to be in their own file with the file name matching including case.  So open up Game.as and drop the following in:
package {
import mx.core.UIComponent; 
import as3isolib.display.IsoView;
import as3isolib.display.scene.IsoScene;
import as3isolib.display.scene.IsoGrid;
import as3isolib.display.primitive.IsoBox;
import as3isolib.display.IsoSprite; 
public class Game extends UIComponent {
private var scene:IsoScene;
private var grid:IsoGrid;
private var view:IsoView;
private var box:IsoBox; 
private function createScene():void {
scene = new IsoScene(); 
// create our grid
grid = new IsoGrid();
grid.cellSize = 25;
grid.setGridSize(8, 8);
scene.addChild(grid); 
// create our view
view = new IsoView();
view.clipContent = false;
view.setSize(width, height);
view.addScene(scene); 
addChild(view);
}
public function Game():void {
super(); 
createScene(); 
// create an IsoBox to test
box = new IsoBox();
box.moveTo(0,0,0);
scene.addChild(box); 
// render the scene
scene.render();
}
}
}
You can now save and exit.  So now that we actually have some code, let's test this!  cd into you're build directory and type "ant".  If you followed all of the instructions, you should now have a file named "game.swf" in your build directory.  Open it up in a browser that has the Flash plugin installed and you should see a basic grid with an isometric box on it!

Check out the tutorials on the as3isolib site for some more info.

All in all, this is about as far as I am, which is kind of sad, since I've been tinkering with this on and off for about a month now, but hey, at least I'm getting some where!

I have another post I'm working on which will teach you how to setup inkscape to create sprites for use with as3isolib.  I was going to try and throw it in here, but this clearly got way longer than I expected :)