BloHx : From Flash to NME to Windows/ OSX/ Linux/ Android/ iOS/ Blackberry/ HTML5...

23.11.2012 4554 1

The Game

This game is a little unfinished game that you can play below.
I especially tried to write it as a Flash developer, using the Flash Player Display List and keep it as is without any optimizations because this is the case of many existing Flash projects...
But because this game is not really an action game, I added another screen with more moving sprites, kind of animations, in order to see how it runs on native NME plateforms. You can see these animations by clicking somewhere on the screen outside of the bricks (on the level or the score i.e.)

The rules

You can click a brick on the screen and drag the mouse to make a selection.
When the bricks on the corners of the selection are of the same color, the selection is valid, the selected blocks are turned and their color changed.
If a brick is turned for the first time, it gives a point.
Points are multiplied by the speed of the action.
The goal is to turn all the bricks on the screen.
The original game is here

Sources

You can download the Haxe/Flash sources here.
From now, we can pass the game to NME.

NME

Quick overview

NME is a framework that maps the Flash Player's API to others plateforms as Neko, C++ or Javascript.
It comes with a command-line tool that gives an unified way to embed assets on the differents target plateforms.

Installation

Download NME here and then proceed the installation as shown.
For this example NME 3.4.3 is used.

The new NME project

We gonna create a new folder and copy/paste the Haxe/Flash sources. These sources can be used directly because NME will automatically remap the flash package into the "nme" package.
As we have seen, NME offers an unified way to embed assets on different plateforms. And in this case, it's not mapped to the default Haxe/Flash assets embeding system.
So the biggest job in order to "translate" a Flash game into a native NME application, is to deal with embeded assets.

Build script

This HXML build script compiles the previous Flash game directly to the Flash target :

-cp src
-lib feffects
-swf bin/BloHxFlash.swf
-swf-header 560:720:24:000000
-main com.filt3rek.blohx.Main
-swf-lib assets/fonts/absender1.swf

Note : -swf-lib assets/fonts/absender1.swf contains a font and its associated class (Absender here...). The other assets are embed directly in the code using @:bitmap and @:sound metadata.
NME has its own build script that is the NMML file format. You can see more details here.
The previous HXML build script can be translated to this NMML :

<?xml version="1.0" encoding="utf-8"?>
<project>
	<meta title="BloHx" package="com.filt3rek.blohx" version="1.0.0" company="filt3rek" />
	
	<!-- output -->
	<app main="com.filt3rek.blohx.Main" file="BloHxNME" path="bin" />
	
	<window background="#000000" fps="24" orientation="portrait" vsync="true" antialiasing="0" />
	<window width="560" height="720" unless="mobile" />
	
	<!-- classpath, haxe libs -->
	<source path="src" />
	<haxelib name="nme" />
	<haxelib name="feffects" />
	
	<!-- assets -->
	<assets path="assets">
		<image path="assets/Haxe_logo_grayscale.png" id="gray" />
		<sound path="sfx/bounce.mp3" id="bounce" />
		<sound path="sfx/explosion.mp3" id="explosion" />
		<sound path="sfx/fired.mp3" id="fired" />
		<sound path="sfx/mutation.mp3" id="mutation" />
		<sound path="sfx/no_match.mp3" id="no_match" />
		<font path="fonts/absender1.ttf" id="absender" />
	</assets>
	
	<!-- DLLs -->
	<ndll name="std" />
	<ndll name="regexp" />
	<ndll name="zlib" />
	<ndll name="nme" haxelib="nme" />
	<!-- optimize JS output -->
	<haxeflag name="--js-modern" if="html5" /><!-- haxe 2.10 ->
        <haxedef name="js-modern" if="html5" /><!-- haxe 2.11 & 3 ->
	
</project>

With the NME tool, the assets will be automatically embeded and we'll get them using the nme.Assets class and their id.

Managing assets by code

When I have to deal with flash assets, I often use a CachedAssets class. It's a central point to get all my project's assets.
In this project, this class looks like com/filt3rek/blohx/Types.hx :

...
@:bitmap( "assets/assets/Haxe_logo_grayscale.png" ) class HaxeLogoGrayscale extends BitmapData { }
@:sound( "assets/sfx/bounce.mp3" ) class BounceSound extends Sound { }
@:sound( "assets/sfx/explosion.mp3" ) class ExplosionSound extends Sound { }
@:sound( "assets/sfx/fired.mp3" ) class FiredSound extends Sound { }
@:sound( "assets/sfx/mutation.mp3" ) class MutationSound extends Sound { }
@:sound( "assets/sfx/no_match.mp3" ) class NoMatchSound extends Sound { }
class CachedAssets { 
	
    static var _gfx	: Hash<BitmapData>;
    static var _sfx	: Hash<Sound>;
    static var _fonts	: Hash<Font>;
	
    public static function initialize() {
	_gfx 	= new Hash();
	_sfx	= new Hash();
	_fonts	= new Hash();
	
	var bmpdBase	= new HaxeLogoGrayscale( 0, 0 );
	var colors	= [ red, green, blue, yellow, purple, brown ];
	for ( color in colors ) {
            var bmpd = bmpdBase.clone();
	    bmpd.colorTransform( new Rectangle( 0, 0, bmpd.width, bmpd.height ), switch ( color ) {
		case red	: new ColorTransform( 1, 0, 0 );
		case green	: new ColorTransform( 0, 1, 0 );
		case blue	: new ColorTransform( 0.3, 0.6, 0.9 );
		case yellow	: new ColorTransform( 1, 1, 0 );
		case purple	: new ColorTransform( 1, 0, 1 );
		case brown	: new ColorTransform( 0.6, 0.3, 0.0 );
	    } );
	    _gfx.set( Type.enumConstructor( color ) , bmpd  );
	}
	bmpdBase.dispose();
		
	_sfx.set( "bounce", new BounceSound() );
	_sfx.set( "explosion", new ExplosionSound() );
	_sfx.set( "fired", new FiredSound() );
	_sfx.set( "mutation", new MutationSound() );
	_sfx.set( "no_match", new NoMatchSound() );
		
	_fonts.set( "absender", new Absender() );
    }
	
    public static function dispose() {
	for ( bmpd in _gfx )
	    bmpd.dispose();
			
	_gfx	= null;
	_sfx	= null;
	_fonts	= null;
    }
	
    public static function getBitmapData( id : String ) {
	return _gfx.get( id );
    }
    public static function getSound( id : String ) {
	return _sfx.get( id );
    }
    public static function getFont( id : String ) {
	return _fonts.get( id );
    }
}

For this game, I've done a particular case because I have embeded a grayscale picture and then I tint it at run-time to obtain several colored bricks...
Anyway, you can have your assets managed as in this example or not, that doesn't matter. But it's a good habbit to have this kind of class because it makes it easier to adapt the Flash behaviour to the NME one.
Now all we have to do is to remove the old flash asset classes (with metadata @:bitmap and @:sound) and correctly map the assets in the CachedAssets class :

...
import nme.Assets;
...
var bmpdBase	= Assets.getBitmapData( "gray" );
...
_sfx.set( "bounce", Assets.getSound( "bounce" ) );
_sfx.set( "explosion", Assets.getSound( "explosion" ) );
_sfx.set( "fired", Assets.getSound( "fired" ) );
_sfx.set( "mutation", Assets.getSound( "mutation" ) );
_sfx.set( "no_match", Assets.getSound( "no_match" ) );
		
_fonts.set( "absender", Assets.getFont( "absender" ) );

That's all !
Ah, I've added 3 lines too, in order to manage pause/resume and exit the game :

Lib.pause();
Lib.resume();
Lib.exit();

You can download the NME sources here.

Compilation

HTML5 version

haxelib run nme test application.nmml html5

You can see it Here

Windows version

haxelib run nme test application.nmml windows

You can download it Here

Android version

haxelib run nme test application.nmml android

You can download it Here
Other targets such as iPhone or iPad compile as well using the same sources.

Commentaires

06.12.2012 à 13:52 hellNstuff

Great tut !

Laisser un commentaire

http://
×