Tuesday, August 28, 2012

Basic animation with NME and drawTiles

In this post I'm going to cover the basics of animation with drawTiles in NME. It builds upon the project in my previous post, Getting started with Haxe and NME.

Source for this example can be downloaded from github.

The fastest way to draw sprites with NME is to use a technique called blitting. This basically means you copy the pixel data from one bitmap into another, and then draw the final composed image to the screen. This is opposed to drawing several bitmaps to the screen, which is generally slower.

In NME this is done via the Tilesheet class and its drawTiles method. (Joshua Granick posted some benchmark numbers, if you'd like to see just how fast drawTiles is.)

Using drawTiles is pretty easy. All we need is a Tilesheet and some tile data, which is an array of Floats telling the Tilesheet what to draw.

First I'm going to declare two instance variables:

Then later I can set them up:

Here I create my Tilesheet with a spritesheet asset, which is basically just an image that contains all my animation frames.

After creating the Tilesheet I tell it the location of my two tiles: The first starts at position 4, 0 and is 8 pixels wide by 16 pixels high. The second starts at position 20, 0 and is also 8x16.

Now I need to set up my tileData, and here's where things get a little more interesting. We're eventually going to ask our Tilesheet to drawTiles using this tileData. The data is formatted as an array of Floats, and each position in the array has a specific meaning. By default, each "tile" is specified by its x position, y position and tile ID. In my array, I'm saying that I want tile ID 0 (the first tile I added to my tilesheet) to be drawn at 10, 10 and also at 20, 10.

So now I've set up my tilesheet and I need a way to draw its tiles every frame. To do that, I set up a listener for the ENTER_FRAME event. The specified method will be called on each frame, allowing me to set up the scene to be rendered.

My onEnterFrame method is going to use a very crude mechanism to change the current animation frame, and I need some instance variables to support it:

OK, here's the method itself:

First we clear graphics. Every Sprite, including the class I'm working with here, has a Graphics member. The tilesheet will draw our tiles to it, and if we don't clear it before drawing then we'll just keep drawing on top of whatever we had last frame.

Next you can see my crude animation mechanism. It's not something I would use in production code, but it's good for this example. Basically, every 500 milliseconds we're going to toggle the tile ID between 0 and 1. Then we specify that position 2 and 5 of our tileData array should be set to this ID. Take a look at the code above, where we initialized tileData, and you can see that position 3 refers to the ID of the first tile and position 5 refers to the ID of the second tile.

Finally, we're ready to drawTiles. We simply provide our Graphics instance and our tileData, and we're set.

drawTiles can do other interesting things too, like scale, rotate or smooth your tiles. Here's the doc, taken from Tilesheet.hx:
Notice how using additional features changes the number of array elements per tile in your tileData.

Here's the complete class:
Run this, and you should be greeted by two happily bouncing chefs:

And there you go. Happy Haxe-ing. :-)

Sunday, August 26, 2012

Getting started with Haxe and NME

NME and Haxe are really amazing. Using them, you can create cross-platform applications for Windows, Mac, Linux, iOS, Android and more.

The history of Haxe is very interesting. It's roots are in ActionScript and Flash development, and so as a language it's very similar to ActionScript. It even uses many of the same classes. As I'm learning Haxe I feel like I'm also learning ActionScript.

In this blog post I'm going to walk through setting up NME and creating a very basic app that displays a bitmap sprite. Full source for this application can be found on github.

Installation

To install NME, check out the instructions. I've been using Sublime Text 2 to write Haxe and build NME projects, and I highly recommend it. Using Sublime Package Control you can install the Haxe Bundle for Sublime Text 2 and get syntax highlighting, code completion, and build tooling.

Project skeleton

First off, let's take a look at the structure of a simple project:
We have three top-level folders:
  • Assets: Where the application icon and other assets will reside.
  • Export: This is where builds will go.
  • Source: Where source files will go.
And three files:
  • nme.svg: An application icon I borrowed from the sample projects. SVG is used so that at compile time the icon can be rasterized and scaled to whatever size(s) the target platform requires. For SVG work I use and recommend the Open Source vector graphics editor Inkscape.
  • NME1.nmml: NMML files are used to configure NME's install tool. This file will specify things like the window size, icon name, etc. We'll walk through it.
  • Main.hx: The only Haxe source file in my simple project.
Go ahead and create a folder structure similar to this. You can grab the SVG file here.

The NMML file

First, let's take a look at the contents of the NMML file:
The app node allows us to specify things about the app, including the class that contains our main method (the application entry point).

The window node indicates the size and orientation of our window.

Next we specify the location of our build directory by setting BUILD_DIR. A subdirectory will be created for each platform we build to.

The classpath node is used to specify where our source files are located.

We can use haxelib nodes to pull in libraries. Since we're using NME we definitely need that.

The assets node allows us to specify how assets are included in our project. Here we are basically saying that the Assets/images directory should become the images directory in our build (we will load images using the path images/<file>) and that we want to include all images except icons.

The ndll nodes allow us to include native libraries. Here we're using the standard ones.

Check out the official documentation for more in-depth info on the NMML file format.

A barebones class

OK, so let's check out a bare-bones, do-nothing class. Create a file in the Source directory called Main.hx:
Every NME application requires a main method to serve as its entry point, which you can see above. The class that implements this method should extend nme.display.Sprite.

In our main class we're basically creating an instance of Main and adding it to Lib.current as a child. Lib.current will, depending on the platform you are targeting, return a different implementation of MovieClip, which is akin to the ActionScript class of the same name. MovieClips are also Sprites. As we'll see next, Lib.current allows you to get and set useful stage properties such as the scaling mode, width, height and pixel density.

If you want to build and test this app from the command line, you can do the following:

nme test NME1.nmml flash

If you're using Sublime Text 2 with the Haxe bundle, you can hit ctrl+shift+b to select your target and then ctrl+enter to build and run. Ta da! A boring white screen. Excellent.

Displaying a bitmap

OK, let's make this slightly more interesting and display a bitmap image on the screen. First, you'll need to grab an image, such as this, and drop it in Assets/images.

Next we could probably use a constructor in our Main class:

Constructors in Haxe simply have the name new. They must invoke their superclass constructor by calling super(). After doing this, we're going to call initialize to set up some stage configuration and then addSprite to display the bitmap.

Here's initialize:

Notice how everything we configure is via Lib.current (the MovieClip) and its stage property. Stage is akin to the ActionScript class of the same name, and represents the main drawing area.

Here I'm saying that the stage should align towards the top left, that it should scale proportionally (with cropping if the stage becomes too small in either dimension) and that it should fill the screen. I'm just doing it this way because I want to be able to see my tiny sprite and I also want it in the same aspect ratio no matter what. StageScaleMode.NO_SCALE is more typical. I encourage you to play around with the possible settings to see what they do.

Here's addSprite:

This function uses the Assets class to load bitmap data from a specified file. Notice how we're specifying the file location as images and not Assets/images because of the configuration in our NMML file.

Bitmap is itself a DisplayObject, and it just so happens that our Main class, due to the fact that it extends Sprite, is also a DisplayObjectContainer. Anything we add as a child will be displayed on the stage.

Here's the complete class, with proper import statements:

Go ahead and run this, and you should see something like this (after hitting esc to exit fullscreen):
So there he is, our happy little chef sprite. I might do more with him later.

Additional resources

There are some excellent tutorials on the NME website I highly recommend. They show more complete program structure, how to properly cache bitmap resources, etc.

Thanks for reading, and feel free to leave any questions or feedback in the comments.