SFML 2.0 finally officially released

29. April 2013

After literally years of waiting, SFML 2 is finally here along with a site redesign. If you've never heard of it, SFML is a C++ library for (mostly) 2D games, including graphics, audio, networking and io functionality. As you can see, there is also a new logo.

There aren't that many changes, this release was mostly about refactoring to eventually support iOS and Android. The 2 release has been waiting on documentation updates.

 

If you have a 1.6 SFML project, here are the code changes ( compiled by SFML user Nexus ) that can affect your code:

 


General

  • CMake instead of specific compiler solutions and makefiles
  • Use SFML_STATIC to indicate static linkage instead of SFML_DYNAMIC for dynamic linkage
  • Changed naming convention for functions from PascalCase to camelCase
System package
  • Added sf::Vector2u typedef for sf::Vector2
  • Added explicit conversion constructors from different vector types
  • All times (sf::Clock, sf::sleep(), ...) are now measured with the sf::Time class instead of float seconds
  • sf::Thread works now with function objects, no more inheritance
  • Split sf::Unicode::Text to high-level sf::String and low-level sf::Utf
  • Removed sf::Randomizer
  • Low-level memory functions operate on void* instead of char*
Window package
  • Added sf::InputStream for customized resource loading
  • Added events JoystickConnected and JoystickDisconnected to track plug/unplug of joysticks
  • Replaced sf::Input with 3 separate classes sf::Mouse, sf::Keyboard and sf::Joystick. They use global inputs, not window-specific ones.
  • Renamed sf::Window::GetEvent() to pollEvent()
  • Sizes are returned as vectors
Graphics package
  • Added low-level graphics API with sf::VertexArray, sf::Vertex, sf::Transform
  • Added sf::RenderTexture as another render target
  • Added viewport and rotation to sf::View
  • Split sf::Drawable functionality into sf::Drawable (stateless interface) and sf::Transformable (convenience base class for transformable entities)
  • Renamed sf::String to sf::Text
  • Renamed sf::PostFX to sf::Shader
  • Dynamic adaption of sf::Font, no more fixed size and character set
  • sf::Font requires the source (file, memory, ...) to remain valid throughout its lifetime
  • sf::RenderWindow::setView() now copies the sf::View
  • sf::Rect stores (left, top, width, height) instead of (left, top, right, bottom)
  • Changed sign of angles (concerns sf::Transformable rotations)
  • Split sf::Image into sf::Texture (OpenGL texture) and sf::Image (pure pixel container).
  • Renamed sf::Drawable::GetCenter(), SetCenter() to sf::Transformable::getOrigin(), setOrigin()
  • Made transformable interface to get size/bounds more uniform, now there are getLocalBounds() and getGlobalBounds()
Network package
  • Added more overloads for sf::Packet's operator<< and operator>>
  • Renamed sf::SocketTCP, sf::SocketUDP to sf::TcpSocket, sf::UdpSocket and made them non-copyable
Audio package
  • Added ability to seek in sound streams and musics
  • Fixed sf::Listener's target that was a relative direction instead of an absolute position

You can read more details about breaking changes in this thread.

 

Programming




Audio in Haxe and NME

29. April 2013

So we've already look at general development, graphics programming and handling input with Haxe with NME, now we are going to take a look at audio support.  This is by far going to be the shortest post of the series, as frankly, it's the simplest.

 

Let's jump right in with playing audio.

 

 

package gfs;

import nme.Assets;
import nme.display.Sprite;
import nme.Lib;
import nme.media.Sound;

class Main extends Sprite
{
	public function new()
	{
		super();
	    var song = Assets.getSound("audio/background.mp3");
		var soundfx1 = Assets.getSound("audio/effect2.wav");
		
		song.play();
		soundfx1.play();
	}
}

 

 

Well, that was pretty straight forward.  There are only a few things to be aware of here.  First, notice we loaded the sounds using the Assets class with the path "/audio/something".  This path needs to be defined in the NMML file.  Here is what mine looks like:

<assets path="Assets/audio" rename="audio" type="audio" include="*" />

The actual directory on your hard disk should be located within the folder Assets.  The next up thing to know is the file formats.  At the end of the day the supported formats are defined by the SDL_mixer library.  Notice how I used loaded the soundfx from a wav file, while the background music as an MP3?  There is a very important reason for this; you can only have one mp3 playing at a time.  Other more "short term" sound effects should be stored in a  lighter format.  Audio is going to be one of those tricky things, as different platforms can play different formats. It's also important to realize that mp3 is a patent encumbered format, so if you are looking to sell your game, be careful with mp3, or they could come back to you looking for licensing fees!  The ogg vorbis format is a free alternative, but isn't as widely supported.

 

Now let's take a look at a slightly more advanced sample:

 

 

 

package gfs;

import haxe.Timer;
import nme.Assets;
import nme.display.Sprite;
import nme.events.Event;
import nme.Lib;
import nme.media.Sound;
import nme.media.SoundTransform;

class Main extends Sprite
{
	var playLeft = true;
	var song : Sound;
	
	public function new()
	{
		super();
	    song = Assets.getSound("audio/background.mp3");
		var soundfx1 = Assets.getSound("audio/effect2.wav");
		
		var soundChannel = song.play();
		
		// Call our sound effect every second... forever.
		new Timer(1000).run = function() {
			soundfx1.play();
		}
		
		soundChannel.addEventListener(Event.SOUND_COMPLETE, onSongEnd );
	}
	public function onSongEnd(event:Event) {
			Lib.trace("Fired");
			var channel = song.play();
			playLeft = !playLeft;
			
			if (playLeft)
				channel.soundTransform = new SoundTransform(1, -1);
			else
				channel.soundTransform = new SoundTransform(1, 1);

			channel.addEventListener(Event.SOUND_COMPLETE, onSongEnd );
		}
}

 

 

This example is a bit more complex to show off a couple of the features of the audio libraries.  You may notice that play() returns a SoundChannel object.  This object has a number of useful features… you can manipulate the playback of the sound using this guy, by applying SoundTransform's like we do here, to pan sound left or right, you can modify the volume, get current playback position, etc…  In this particular example, we load our two sound effects, start the background music playing, then create a timer that fires ever second, playing our second sound effect over and over and over.

We also wire up an event handler that will be fired when your soundChannel gets to the end ( SOUND_COMPLETE event ).  When that occurs, we toggle the sound to either play only on the left channel, or right channel.  We then recursively wire up our onSongEnd event on our newly created SoundChannel.  This code worked perfectly on every tested platform, although Android had some weird issues… it didn't play properly at first, but once I lost and regained focus, it worked perfectly.

 

So, what about Video?

This is one area current NME is a bit lacking.  There are projects out there that provide native video playback on iOS as well as this project for playing back webm encoded video files, otherwise I believe you are currently out of luck.  So if you need to play cut screens, you are currently left rolling your own solution for each platform.  Fortunately, I do not need video support. :)

,




Rendering a Tilesheet to a Sprite in Haxe/NME

27. April 2013

One of the downsides to using the Tilesheet class in NME is that it can't receive events.  Just as earlier on we created a sprite object to hold our bitmap when we wanted it to receive events, how exactly do you handle this when working with the Tilesheet class?  In the Haxe/NME Input tutorial, I got asked exactly this question:

 

I tired to wrap the animation of previous tutorial before into this one.

but since the animation is an tileSheet object it doesn't want to be wrapped into a Sprite
it said

nme.display.Tilesheet should be flash.display.DisplayObject
for:
sprite.addChild(sprites); // sprite is my tileSheet and sprites is a sprite

any idea to solve the problem or it's going to come in a next tutorial

 

Hmmm… good question…  short answer is, I didn't know.  Slightly longer answer is, when you call drawTiles, you can specify where to draw.  In the earlier example we simply drew to the stage.  So, we simply create a Sprite around an empty Bitmap add it to the scene and add the sprite to the scene.

Let's look at some code:

package gfs;

import nme.Assets;
import nme.display.Bitmap;
import nme.display.DisplayObject;
import nme.display.Graphics;
import nme.display.SpreadMethod;
import nme.display.Sprite;
import nme.display.Tilesheet;
import nme.events.Event;
import nme.geom.Rectangle;
import nme.Lib;
import nme.ui.Keyboard;
import nme.events.KeyboardEvent;


class Main extends Sprite
{
	private var currentFrame: Int = 5;
	private  var sprites: Tilesheet;
	var sprite:nme.display.Sprite;
	
	public function new()
	{
		super();
		sprites = new Tilesheet(Assets.getBitmapData("img/mechwarrior.png"));
		var tileData = new Array<Float>();
		
		for (i in 0...11)
		{
			sprites.addTileRect(new Rectangle(0, i * 80, 90, 80));
		}
		
		sprite = new Sprite();
		var bmp = new Bitmap();
		bmp.width = 90;
		bmp.height = 80;

		sprite.addChild(new Bitmap());
		
		sprite.x = 0;
		sprite.y = 0;
		
		sprites.drawTiles(sprite.graphics, [0, 0, currentFrame,4],false,Tilesheet.TILE_SCALE);
		
		Lib.current.stage.focus = sprite;
		sprite.addEventListener(KeyboardEvent.KEY_DOWN, function(e) {
			graphics.clear();
			sprite.graphics.clear();
			if (e.keyCode == Keyboard.DOWN)
			{
				if (++currentFrame == 11) currentFrame = 0;
			}
			else if (e.keyCode == Keyboard.UP)
			{
				if (--currentFrame == 0) currentFrame = 10;
			}
			sprites.drawTiles(sprite.graphics, [0,0, currentFrame,4], false, Tilesheet.TILE_SCALE);
		});
		Lib.current.stage.addChild(sprite);
	}
}

 

You can run this application by clicking here. Press up and down to animate.

 

And there you go.  If you are working with a sprite animation populated by a Tilesheet that you want to receive events directly, this is one option.  A couple of things though…  handling keyboard events in this case works really really really poorly… it only works in Flash…  generally you will want to handle keyboard events at the stage level.  This code was more a proof of concept than anything else.  Simply put, it's probably a really stupid way to do this.

,




A guided tour of the Dreemchest Lua based game engine

25. April 2013

 

As you may know from previous posts I am rather a big fan of Lua based game engines.  When I learned about a new one completely off my radar, I just had to check it out.  The game engine in question is Dreemchest.

image

 

As I mentioned earlier, Dreemchest is scripted using Lua.  Underneath Dreemchest is powered by a C++ core.  In terms of other Lua game engines, Dreemchest is probably most similar to Corona in scope.  It comes with a WYSIWYG editor and somewhat uniquely, enables you to use Flash to create your user interface.  Unlike Corona, you don’t need to authorize against and build on their servers, everything is done locally, I know some people really hate that about Corona and Gideros ( and more recently Loom ). Oh yeah, it’s also free(for now?).  Let’s jump in and take a look at Dreemchest.

 

First things first, you need to download Dreemchest, which you can do right here.  It is available for Windows and MacOS, although I have to admit, the MacOS version seems to be a lot less stable right now, so if you have a choice I would consider choosing the Windows version.  There is no installer, simply download the archive, extract it then run composer.  Dreemchest seems to be a Qt app, so I’m a bit shocked a Linux build isn’t available.  Then again, Linux is a fairly small sub-set of the population, so maybe that’s a down the road feature.

 

Meet Dreemchest Composer.

 

Dreemchest Composer in action

image

This is the WYSIWIG environment in action with the Animation sample loaded.  Currently there are over 20 samples available showing you how to perform various actions in Dreemchest.  As you can see from the Window above, it’s a pretty sparse environment, but most of the information you need is available.  Across the top is the toolbar you would use to configure and run your application.  Below the is the WYSIWYG editing area and below that is the output panel.  On your right hand side is the Property window, which is populated dynamically by your script objects, allowing you to view and configure values visually instead of in code.  Below that are your assets, that you can import, create then drag and drop into your scene.

 

The UI itself is incredibly customizable, every dialog can be detached, moved or closed, leaving you law things out exactly as you want.

image

 

Coding and documentation

 

So, where exactly do you do the coding?  If you have the Animation sample open, take a look at the assets panel and you will see a pair of script objects, App and Hero.

image

 

Double click one of these script files and it will open in the integrated text editor.

image

It’s a fairly barebones editor, but it does what you need including syntax highlighting, auto-completion and automatic indention.  It’s nice not having to switch apps to edit code.

 

The programming language itself is standard Lua 5.1, with an class inheritance system.  If you know Lua you will be immediately comfortable with Dreemchest.  If you press play or F5 to run your application, it runs directly inside Dreemchest:

image

As of right now, debugging options are quite light.  You can alter position, from portrait to landscape, simulate home button press and not much else.  Oddly enough, once the application is running, you see the options traditional debugging options, such as step in, step out and continue.  That said, I cant figure out how to add an actual breakpoint.  My guess is, this is a feature under active development.  I look forward to it too, as for now you would be limited with printing to the output window while debugging.  Build and load times are virtually non-existent, which is nice.

 

From a coding perspective, there is a pretty good amount of documentation, especially for such a young project.  As mentioned earlier, there are currently 20+ samples included with the download.  There are a series of tutorials available here as well as an API reference available here.  The API is quite straight forward, somewhat minimal, but still under developed.  Pretty much everything you need to create a 2D game is currently there, including graphics, tweening, audio and physics.  For physics, there is also an integrated shape editor which is rather convenient.  Still under development, new functionality is being added with each release.  This is critical though, as you don’t get source code, so you need all functionality needs to be in box.

 

Flashing

 

Perhaps the most innovative feature of Dreemchest is the ability to embed and communicate with Flash objects for creating your UI layer.  You can included an SWF file just like you do any other graphic file.  The swf file can contain ActionScript2 code, and the two languages can communicate back and forth.  Here is a simple example from the SDK on working with a Flash animation, showing how you can load and communicate between the languages.  uiButtons is the swf file that has been added to the scene.

class "Main"( StageObjectContainer )

function Main:main()
    -- Register necessary functions for Flash UI
    UIManager.registerFunction( 'nativeSetPitch', function( value ) trace( 'Pitch set to: '..value ) end )
        
    -- Attach to events dispatched from Flash UI
    UIManager.attachListener( 'uiStop', self )
    UIManager.attachListener( 'uiToggleMusic', self, 'onMusicToggle' )
    
    local ui = uiButtons.new()
    self:attach( ui )
        
    -- Notify Flash UI by dispatching an event
    UIManager.dispatchEvent( 'onRefresh', { version = 104, message = 'hi there!' } )
end
    
function Main:uiStop( e )
    trace( 'Stop the music' )
end
    
function Main:onMusicToggle( e )
    if e.pause then
        trace( 'Pause music' )
    else
        trace( 'Continue music playback' )
    end
end

This allows you to use the rich UI functionality of Flash/ActionScript for your UI layer, while performing game logic and rendering in Lua.

 

Building your application

 

When it comes to creating and deploying your application, that’s a pretty simple process.  Simply select the File->Export menu and select the platform.  You need to have a Mac to build iOS or OSX target.  You need to install the Android or iOS SDK and point Dreemchest at the proper directory before you can export to either platform.  The results of the build (an apk in the case of Android) are in the output subdirectory although I had to do a bit of searching to figure this out.

 

image

 

Conclusion

 

Dreemchest is certainly a young engine, but it has a great deal of potential.  I did experience crashes and a few UI glitches, although the newest release seems a great deal more stable.  I’m actually quite surprised by just how much it did improve in just a couple weeks, this bodes well for the future. This is certainly an engine worth keeping an eye on, especially if you like Lua and are targeting iOS or Android.  It may not be for everyone, if you need source code for example, Moai is a better fit.  But if you are looking for an all in one accessible toolkit, Dreemchest is a good pick.  Of course, it’s free too, so you’ve got nothing to lose by checking it out.

Programming ,




Input in Haxe and NME

24. April 2013

In the past we covered basic program structure as well as using graphics using Haxe and NME.  In this section we are going to look at handling input.  A number of these samples, such as multi touch, will only work on a device, although we will briefly look at how to create device specific code that still compiles on other platforms.  Alright, let's jump right in.

 

First lets look at the basics of handling touch and mouse click events.

 

Mouse click and finger touch event handling

 package gfs;

import nme.Assets;
import nme.display.Bitmap;
import nme.display.Sprite;
import nme.events.Event;
import nme.events.TouchEvent;
import nme.events.MouseEvent;
import nme.Lib;


class Main extends Sprite
{
	private var sprite:Sprite;
	
	public function new()
	{
		super();
		
		var img = new Bitmap(Assets.getBitmapData("img/mechwarriorFrameScaled.png"));
		
		//Bitmap unfortunately cannot receive events, so we wrap it in a sprite
		sprite = new Sprite();
		sprite.addChild(img);
		
		sprite.x = Lib.current.stage.stageWidth / 2 - sprite.width / 2;
		sprite.y = Lib.current.stage.stageHeight / 2 - sprite.height / 2;
		
		sprite.addEventListener(MouseEvent.CLICK, mechClicked);
		Lib.current.stage.addEventListener(TouchEvent.TOUCH_TAP, onTouch);
		Lib.current.stage.addEventListener(MouseEvent.CLICK, onClick);

		Lib.current.stage.addChild(sprite);
	}
	
	public function mechClicked(event: MouseEvent)
	{
		sprite.x = Lib.current.stage.stageWidth / 2 - sprite.width / 2;
		sprite.y = Lib.current.stage.stageHeight / 2 - sprite.height / 2;
		event.stopImmediatePropagation();
	}
	
	public function onTouch(event: TouchEvent)
	{
		sprite.x = event.stageX - sprite.width / 2;
		sprite.y = event.stageY - sprite.height / 2;
	}
	
	public function onClick(event: MouseEvent)
	{
		sprite.x = event.stageX - sprite.width / 2;
		sprite.y = event.stageY - sprite.height / 2;
	}
	
} 

When you run this code you should see:

1

The mech will move wherever you click or touch.  If you click on the mech sprite, it will move back to the centre of the screen.

 

Now back to the code. I was informed that I didn't need to create a static main function when working with NME, so in my prior examples… ignore that bit. :)

Therefore we now start of in our constructor new.  First we create an image, a small version of our now familiar mech image.  There is a catch though, even though it has the method addEventListener, a Bitmap object can't actually receive events.  Therefore we are creating a Sprite object to hold our Bitmap.  Next up we centre the sprite to the screen.  Then we wire up sprite to receive MouseEvent.CLICK events, which will causer it to call the function mechClicked.  We also wire up TouchEvent.TOUCHT_TAP and MouseEvent.CLICK event handlers to the actual stage.

It's important to realize the order things are handled when a click or touch occurs.  It will ultimately be the object that is touched that get's first crack at the event, then it's parent, then it's parent, etc…  this is called 'bubbling'.  It's a very important thing to get your head around, as consider the current situation…  we are setting up a click handler in our mech sprite that handles the click, causing the sprite to be re-entered back to the middle of the screen if clicked.  Then the stage handles the event and moves the sprite to where the user clicked, effectively overwriting the actions the Sprite's event handler took.  In this case we want to stop handling the event  once the mech is clicked, so it's parent's handler won't run.  This is accomplished by calling event.stopImmediatePropagation().  The only other thing to notice is the different event types passed in to the various event handlers.

There is however one current gotcha in the above code… for CPP targets it doesn't actually work.  The call to stopImmediatePropagation() doesn't actually do what it says.  I reported this on the forums and most impressively, they already fixed the bug!  Colour me impressed on that one.  So, depending on when you are reading this, mechClicked() may not appear to be working if run on one of the CPP targets.  It does however work just fine on Flash and HTML5.

If you aren't working from NME sources, you can work around with this simple fix:

class Main extends Sprite
{
	private var sprite:Sprite;
	var clickHandled = false;
	
	public function new()
	{
		super();
		
		var img = new Bitmap(Assets.getBitmapData("img/mechwarriorFrameScaled.png"));
		
		//Bitmap unfortunately cannot receive events, so we wrap it in a sprite
		sprite = new Sprite();
		sprite.addChild(img);
		sprite.x = Lib.current.stage.stageWidth / 2 - sprite.width / 2;
		sprite.y = Lib.current.stage.stageHeight / 2 - sprite.height / 2;
		
		sprite.addEventListener(MouseEvent.CLICK, mechClicked);
		
		Lib.current.stage.addEventListener(TouchEvent.TOUCH_TAP, onTouch);
		Lib.current.stage.addEventListener(MouseEvent.CLICK, onClick);
		
		
		Lib.current.stage.addChild(sprite);
	}
	
	public function mechClicked(event: MouseEvent)
	{
			sprite.x = Lib.current.stage.stageWidth / 2 - sprite.width / 2;
			sprite.y = Lib.current.stage.stageHeight / 2 - sprite.height / 2;
			clickHandled = true;
	}
	public function onTouch(event: TouchEvent)
	{
		sprite.x = event.stageX - sprite.width / 2;
		sprite.y = event.stageY - sprite.height / 2;
	}
	
	public function onClick(event: MouseEvent)
	{
		if (clickHandled) {
			clickHandled = false;
			return;
		}
		sprite.x = event.stageX - sprite.width / 2;
		sprite.y = event.stageY - sprite.height / 2;
	}
}

Basically you just set a flag that the current click action has been handled.  Of course, this system falls on it's face once you start looking at multi-touch, as we will shortly

 

Keyboard Handling

So that's the basics of clicking and touching, now let's take a look at using keyboard control.  This will only work on devices with a physical keyboard.

package gfs;

import nme.Assets;
import nme.display.Bitmap;
import nme.display.Sprite;
import nme.events.Event;
import nme.events.KeyboardEvent;
import nme.Lib;
import nme.ui.Keyboard;


class Main extends Sprite
{
	private var sprite:Sprite;
	
	public function new()
	{
		super();
		
		var img = new Bitmap(Assets.getBitmapData("img/mechwarriorFrameScaled.png"));
		
		//Bitmap unfortunately cannot receive events, so we wrap it in a sprite
		sprite = new Sprite();
		sprite.addChild(img);
		
		sprite.x = Lib.current.stage.stageWidth / 2 - sprite.width / 2;
		sprite.y = Lib.current.stage.stageHeight / 2 - sprite.height / 2;

		Lib.current.stage.addEventListener(KeyboardEvent.KEY_UP, function(event) {
			if (event.keyCode == Keyboard.RIGHT)
			{
				if (event.altKey || event.ctrlKey || event.shiftKey)
					sprite.x += 10;
				else
					sprite.x += 1;
			}
			if (event.keyCode == Keyboard.LEFT)
			{
				if (event.altKey || event.ctrlKey || event.shiftKey)
					sprite.x -= 10;
				else
					sprite.x -= 1;
			}
		});

		Lib.current.stage.addChild(sprite);
	}
	
	public static function main()
	{
		Lib.current.addChild(new Main());
	}
} 

When you run this code, you can use the left and right arrows to move the sprite left or right.  Holding down the alt key, shift key or control key will cause the sprite to move by 10 pixels, otherwise it moves by 1 pixel in the given direction.

As you can see, handling keyboard events is almost exactly the same as handling mouse and touch events.  You simply wire up the stage to listen for the event KeyboardEvent, in this case KEY_UP.  You simple compare the keyCode of the event against the enum specified in Keyboard to see if your key has been pressed.  There are also a series of flags, altKey, ctrlKey and shiftKey that tell you the status of each of these keys.

One important thing to note, you do not use KeyboardEvent to handle text field input, instead use the methods of TextField.

 

Accelerometer/motion control handling 

Now let's take a look at how to handle the Accelerometer.  This code will compile on any platform, but will only work on mobile platforms for obvious reasons.

 

package gfs;

import nme.Assets;
import nme.display.Bitmap;
import nme.display.Sprite;
import nme.events.Event;
import nme.events.AccelerometerEvent;
import nme.Lib;
import nme.sensors.Accelerometer;
import nme.ui.Accelerometer;


class Main extends Sprite
{
	private var sprite:Sprite;
	
	public function new()
	{
		super();
		
		var img = new Bitmap(Assets.getBitmapData("img/mechwarriorFrameScaled.png"));
		
		//Bitmap unfortunately cannot receive events, so we wrap it in a sprite
		sprite = new Sprite();
		sprite.addChild(img);
		
		sprite.x = Lib.current.stage.stageWidth / 2 - sprite.width / 2;
		sprite.y = Lib.current.stage.stageHeight / 2 - sprite.height / 2;

		Lib.current.stage.addEventListener(Event.ENTER_FRAME, onFrameEnter);
		Lib.current.stage.addChild(sprite);
	}
	
	public function onFrameEnter(event:Event) {
		#if (android || ios)
		if (Accelerometer.isSupported) {
			var y = nme.ui.Accelerometer.get().y;
			Lib.trace(y);
			if (y < 1 && y > 0.6) sprite.y-=5; // straight up and down
			else if (y < 0.4 && y > 0.0) sprite.y+=5;  // turned 90 degrees from user
		}
		else
			Lib.trace("No Accelerometer support");
		#else
			Lib.trace("Not a mobile target");
		#end
	}
	
	public static function main()
	{
		Lib.current.addChild(new Main());
	}
}

When you run this code, our trusty mech sprite is drawn centred to the screen.  If the phone is straight up and down ( parallel to your head ) nothing will happen.  As you tilt the phone away from you, for the first 40 or so degrees the sprite will move up.  Then a dead zone, then for the next 40 os so degrees the sprite will move down, until you are holding the phone perpendicular to you, at which point the sprite will stop moving.

Now for a bit of a red herring… there are Accelerometer events… THEY DONT WORK!  Don't go that route.  The events are simply never fired.  Instead you need to poll the Acelerometer when you want data.  In this case we are going to use the ENTER_FRAME event, which is fired at the beginning of each frame, causing the onFrameEnter function being called.

In onFrameEnter, we have our first compiler conditional.  If you are used to pre-processor directives, this will be familiar with you.  Basically code starting with the # symbol tell the compiler what to id.  In this case, code within the #if (android || ios) will only be executed if those values are true.  If it is an iOS or Android device, we simply read the G value of the y axis.  A value of 1 indicates a motionless phone straight in from of you.  A value of 0 is a motionless phone perpendicular to you.  You can get the motion values of all 3 axis and use them to determine orientation as well as movement.

 

Handling multitouch

Finally let's take a look at multitouch support.  Once again you obviously need a multi-touch capable device to run this sample.

 

 

package gfs;


import nme.Assets;
import nme.display.Bitmap;
import nme.display.Sprite;
import nme.display.Stage;
import nme.display.StageScaleMode;
import nme.events.Event;
import nme.events.TouchEvent;
import nme.Lib;
import nme.ui.Multitouch;
import nme.ui.MultitouchInputMode;


class Main extends Sprite
{
	private var sprites: Array<Bitmap>;
	
	public function new()
	{
		super();
		
		sprites = new Array<Bitmap>();
		
		sprites.push(new Bitmap(Assets.getBitmapData("img/mechwarriorFrame.png")));
		sprites.push(new Bitmap(Assets.getBitmapData("img/mechwarriorFrame.png")));
		sprites.push(new Bitmap(Assets.getBitmapData("img/mechwarriorFrame.png")));
		sprites.push(new Bitmap(Assets.getBitmapData("img/mechwarriorFrame.png")));
		
		for (i in 0 ... sprites.length) {
			sprites[i].x = Std.random(800);
			sprites[i].y = Std.random(1280);
			Lib.current.stage.addChild(sprites[i]);
		}

		Lib.current.stage.addEventListener(TouchEvent.TOUCH_BEGIN, function(e) {
			sprites[e.touchPointID].x = e.localX;
			sprites[e.touchPointID].y = e.localY;
		});
	}

}

Here is the code running on my Galaxy Note.  Each mech sprite is positioned where you touched.  Up to four sprites/touches can be tracked in this example.

Export 04

So, each sprite represents the location I most recently touched with each finger. 

 

We simple create an array of images all holding the same image, one for each of our four fingers.  We then randomize it's starting location ( for no particular reason ) then add it to the stage.  Touch is handled exactly as it was before, the only real difference is the event can be fired a number of times.  You determine if it is multiple touch by checking the touchPointID value of event.  This ID value can be thought of as the index value of your finger… so if you are using a single finger, it will have a value of 0.  If you are using 3 fingers, and it is the third touchpoint, the value will be 2.  

 

One word of warning, there is mention in the docs of GESTURE modes… such as ZOOM, etc… these do not exist in NME.  If you want gesture support, you need to roll it yourself.

 

So that's IO in Haxe…  I have to say, other then a bug ( which was fixed almost instantly! ) and a red herring in the documentation about gesture support, that was a painless experience and has all the functionality I need.  Of course, I just used a portion of what's there… you can also mouse over, key up, mouse enter, etc...

 

I did run into a few annoyances with FlashDevelop though.  First, if you run an cpp target project, while one is already running on your device, not only will it fail, it will bork the debugger forcing you to reset FlashDevelop.  It sounds like a mild annoyance, but I did it probably 15 times!  Another annoyance is Flashdevelop loses intellisense when inside anonymous methods, or whatever Haxe/Flash calls them.

,