3 Days into the 3-Week Challenge

.. and we have progress! See above. Use the keyboard to control the ‘player’.

The first thing you will noticed is that there is a world populated with solid blocks and some orange circle things that may look a little like collectables 😛 To generate this level I decided to take a page out of Notch’s book and build the levels at the pixel level in Paint.NET. That way the image editing software becomes the level editor. So as an example, the data that builds the level for above looks like:

That’s a 50×50 pixel image which represents a world 50×50 tiles wide. Each pixel in the image has a colour which corresponds to a tile type in the game. Black is a solid wall, red is the player spawn point and orange is a ‘collectable’. As the game develops we will be adding more tile types and hence colours.

At runtime all I do is load the level data image and loop through the pixels, grab the colour value and populate the world with the appropriate object. A problem I soon encountered however is that for some reason on different platforms Haxe reads the colour value different. This made things problematic so instead what I have done is make another 8×8 image as a “key”:

Loading this key first I can then determine what colour the platform will be recognising a particular tile type as. So to generate the level the code looks like:

[codesyntax lang=”actionscript3″]

class LevelManager 
{
	public static var TYPES : Hash<Class<Dynamic>>;	

	public var gridW : Int;
	public var gridH : Int;
	public var tiles : Array<BaseObject>;

	public function new() 
	{
		if (TYPES == null)
		{
			var objectTypes = [null, SolidBlock, SpawnPoint, Ring];			
			TYPES = new Hash<Class<Dynamic>>();
			var bmd =  Assets.getBitmapData("assets/levels/key.png");
			if (bmd == null) throw new Error("key png is null for some reason!");
			var i = 0;
			for (y in 0...bmd.height) for (x in 0...bmd.width) if(i<objectTypes.length) TYPES.set("" + StringTools.hex(bmd.getPixel(x, y), 6), objectTypes[i++]);
		}
	}

	public function loadLevel(stageIndex:Int, levelIndex:Int) 
	{
		var bmd =  Assets.getBitmapData("assets/levels/s" + stageIndex + "_l" + levelIndex+"/world.png");
		gridW = bmd.width;
		gridH = bmd.height;
		tiles = [];

		for (y in 0...gridH)
		{
			for (x in 0...gridW)
			{
				var c = StringTools.hex(bmd.getPixel(x, y), 6);
				var t = TYPES.get(c + "");
				if (t == null) { continue; }			
				var o : BaseObject = Type.createInstance(t, []);
				o.x = x * Game.GRID_SIZE;
				o.y = y * Game.GRID_SIZE;
				Game.I.addObject(o);
				tiles[y * gridW + x] = o;
			}			
		}
	}
...

[/codesyntax]

Once I had the level populating I started getting the basics of the physics sorted. At first I thought it was going to be a nightmare as in the original version of the game it appeared as if the whole world rotated about the player (see video for reminder), I worried about how I was going to handle the complex physics of a grid at odd angles while continually rotating. After a while however I realised that what was actually going on was that the world was standing still and all that was happening was that the camera was rotating at same rate at which the gravity vectyor was changing, thus giving the illusion of a rotating world, eg:

Once I realised this fact it made my life a whole lot easier. Calculating the physics for the world should now just be a matter of solving a circle against a static grid without rotations. I decided to go with my own physics solution rather one of the existing solutions such as Box2D or Nape as I thought that it should be pretty simple to calculate and I knew from a previous project that using Box2D or Nape would have issues at the joins between tiles.

The solution it turns out took a little longer than I thought but I eventually cracked it. The key was to use the Separating Axis Theorem with Voroni Regions, there is a great tutorial on it over at magnet software, they have a handy SWF that demonstrates the concept really well:

As can be seen from above that all you need do is split the problem up into a grid, then in turn check each of the 8 neighbouring cells from the current cell. The north, east, south and west cells can be classed as one type and only need to have their relevant axis checked against the radius of the player wheres the corner cells need to be checked against the distance from the closest point. In code this looks something like:

[codesyntax lang=”actionscript3″]

// From Player.hx

override public function update(delta:Int) : Void
{
	#if !mobile
	if (Ctrl.instance.isDown("up")) vel.y -= 1;
	if (Ctrl.instance.isDown("left")) vel.x -= 1;
	if (Ctrl.instance.isDown("right")) vel.x += 1;
	//if (Ctrl.instance.isDown("down")) vel.y += 1;
	#end

	if (Ctrl.instance.mouseDown) vel.y -= 1;

	var d = delta * 0.01;
	vel.x += gravity.x * d;
	vel.y += gravity.y * d;		

	var newPos = new Vec2(x + vel.x * d, y + vel.y * d);
	var ntx : Int = Std.int(newPos.x / Game.GRID_SIZE);
	var nty : Int = Std.int(newPos.y / Game.GRID_SIZE);				

	checkTileCollide(ntx, nty, ntx - 1, nty + 1, newPos, vel);
	checkTileCollide(ntx, nty, ntx + 1, nty + 1, newPos, vel);
	checkTileCollide(ntx, nty, ntx - 1, nty - 1, newPos, vel);
	checkTileCollide(ntx, nty, ntx + 1, nty - 1, newPos, vel);
	checkTileCollide(ntx, nty, ntx, nty + 1, newPos, vel);
	checkTileCollide(ntx, nty, ntx, nty - 1, newPos, vel);
	checkTileCollide(ntx, nty, ntx + 1, nty , newPos, vel);
	checkTileCollide(ntx, nty, ntx - 1, nty , newPos, vel);	

	x = newPos.x;
	y = newPos.y;
}

private function checkTileCollide(fromTX:Int, fromTY:Int, toTX:Int, toTY:Int, pos:Vec2, vel:Vec2) : Bool
{
	var tile = game.level.getTile(toTX, toTY);
	var dTX = fromTX - toTX;
	var dTY = fromTY - toTY;
	if (tile != null && tile.is(SolidBlock))
	{				
		if (dTX == 0)
		{
			var d =  Math.abs(pos.y-((toTY - fromTY) > 0?toTY * Game.GRID_SIZE:fromTY * Game.GRID_SIZE));
			if (d < radius)
			{
				pos.y += dTY * (radius - d);
				vel.y = 0;
				return true;
			}
		}
		if (dTY == 0)
		{
			var d =  Math.abs(pos.x-((toTX - fromTX) > 0?toTX * Game.GRID_SIZE:fromTX * Game.GRID_SIZE));
			if (d < radius)
			{
				pos.x += dTX * (radius - d);
				vel.x = 0;
				return true;
			}
		}			
		else
		{	
			var tp = new Vec2((dTX>0?fromTX:toTX)*Game.GRID_SIZE, (dTY>0?fromTY:toTY)*Game.GRID_SIZE);				
			var vToCorner = new Vec2(tp.x - pos.x, tp.y - pos.y);			
			if (vToCorner.lengthSqr() < radius * radius)
			{					
				var ang = Math.atan2(vToCorner.y, vToCorner.x);							
				pos.x = tp.x - Math.cos(ang) * radius;
				pos.y = tp.y - Math.sin(ang) * radius;				
				//vel.x = vel.y = 0;
				return true;
			}			
		}
	}
	return false;
}

[/codesyntax]

Its not 100% perfect, there is some oddness when the player hits a corner but will do for now.

On the art side of the project Moh has been making good progress coming up with themes for the game. We have been playing around with the idea that the player is a Hamster lost in space, which I really like the idea of. To test this idea he made little mock-up, which looks great:

You may have noticed that currently the game is in Flash. That’s because with NME you can target Flash as one of your outputs. This makes developing and testing the game alot easyier (a lot faster to compile and run). I have however been very aware of the problems I could cause myself if I developed the whole game solely in flash and only testing on mobile right at the end. Trying to track down an obscure problem in a fully written game would be a nightmare. So I have been making progress with getting the game to run on my iPhone 4.

One of the problems I faced (and I banged my against the wall for a while on this one) was that for some reason when the level was populating from the PNG, certain tiles weren’t being built. I couldn’t for the life of me work out why. To cut a long story short, apparently when building for iOS in Haxe you MUST put the super call in the constructor BEFORE any other call, else the code before the super call in the constructor wont be executed:

[codesyntax lang=”actionscript3″]

class Player extends BaseObject
{	

	public function new() 
	{		
		trace("This will not be executed when built for iOS but WILL be executed when built for flash");	
		super();
		trace("This will be execute on flash AND iOS");	
	}

...

[/codesyntax]

A small thing to remember but quite a gotcha for the NME Haxe newbie!

Another issue I have run into is the fact that my iPhone currently has iOS 5.1 on it, this means that to use it as a testing platform I had to upgrade my Macbook to OSX Lion which meant I have to leave it running over night and this morning downloading and installing. Not a biggie as I have been meaning to upgrade for a while anyways, but an inconvenience when you want to sit down to test your shiny new game out!

We have quite a way to go, but im happy with the progress we have made in 3 days thus far 🙂

Lets Make a Mobile Game in 3-Weeks with Haxe & NME

I have decided that I would like to learn more about mobile game development. Its an exciting area of the games industry at the moment with so many frameworks and languages to choose from to develop with. The plethora of choice however can be a hindrance, what are the best frameworks and language for this particular task? Haxe with NME?  C# MonoTouch with Monogame? or even Javascript with Titanium? One can only go so far just reading about them, eventually you have to jump in and try them out for yourself.

So on that note I have decided to team up with an artist colleague (Moh ‘Mohzart’ Mukhtar) from work to create a mobile game in three weeks of evenings and weekends. Three weeks is an ambitious target for a game on any platform let alone mobile with its added complications. The primary purpose of this project however is to gather experience on the process of making mobile games using a given langauge, framework and platform. Having a longer time-scale I feel would deter from this, the primary motivation. Having said that however, I hope that in three weeks we will have something that to be reasonably proud of.

For this particular game I have decided to explore Haxe with NME. Haxe is a programming language I have been using for my personal projects for about a year now and is ideally suited to mobile development due to its ability to target multiple platforms with the same codebase. NME is a framework written in Haxe that emulates the Flash API and thus provides an interface I am extremely familiar with having used it for many years on personal and professional games. I dabbled with NME about a year ago while at the TryHarder conference however things have moved on with the project a lot since then and im looking forward to getting stuck in and playing around with it some more.

In theory Haxe with NME should give us the ability to target Flash, HTML5, OSX, Linux, Window, iOS, Android and WebOS all with the same codebase. I hope this to be the case, however, initially we will be focusing on getting it to run on Flash and iOS, the other platforms will be of secondary concern.

So as for the actual game itself. Over the last week or so we have been racking our brains trying to come up with a game that will be suitable for this project. To be suitable it must be achievable within three week, be compatible for touch based devices, suit both our skill sets and preferably not been done before on mobile. A tough set of requirements.

We wrote down a few ideas in a GDoc, but the best one and the one we have decided upon is to do a remake / variant on the “Chaos Emerald” bonus stage from Sonic1 on the Genesis. As a quick reminder of what that looks like:

It wont be a direct rip (before I have the Sega lawyers knocking down my door) but the inspiration will certainty come from that game. The reason why we finally chose this idea is because it should work quite well on mobile (single button press with accelerometer tilting) and is a fairly simple game code and art wise so hopefully we should be able to complete it within three weeks. As an added bonus I have been unable to find this already existing on the App Store. Let me know if you have seen it done already!

I intend to continue to update on the progress of the game as we go along on this blog 🙂

Fingers crossed we can pull it off!

On Porting RobotLegs2 & SwiftSupenders2 to Haxe

I originally hoped that this post would be about my successful completion of a RobotLegs2 port to Haxe however something else has come up (more on that in a later post) so instead im just going to talk about the process and progress of the port thus far.

So although there is already an excellent RobotLegs 1 Haxe port out there by David Peek, I decided I would like to try to port the brand new Robot Legs 2 Framework  which offers a great many improvements over the original.

Rather than beginning the port from scratch I decided to use as3hx to take the legwork out of converting the AS3 code to Haxe code. To get the tool you must first checkout the library from its google code repo at: http://caffeine-hx.googlecode.com/svn/trunk/projects/as3hx/

Once downloaded its just a simple matter of compiling the source into a neko executable:

[codesyntax lang=”powershell” lines=”normal”]

haxe as3hx.hx

[/codesyntax]

Then you can run it with:

[codesyntax lang=”powershell” lines=”normal”]

neko as3hx.n

[/codesyntax]

To convert a AS3 project give it an input and output folder:

[codesyntax lang=”powershell” lines=”normal”]

neko as3hx.n -vector2array -uint2int robotlegs2 robotlegs2out

[/codesyntax]

In this case the input folder is the source download from the RobotLegs2 GitHub page.

It will start to convert but will get stuck:

[codesyntax lang=”powershell” lines=”normal”]

C:/Users/MikeC/Desktop/as3hx/robotlegs2/src/robotlegs/bender/extensions/eventCommandMap/api/IEventCommandMap.as
C:/Users/MikeC/Desktop/as3hx/robotlegs2out/robotlegs/bender/extensions/eventcommandmap/api/IEventCommandMap.hx
C:/Users/MikeC/Desktop/as3hx/robotlegs2/src/robotlegs/bender/extensions/eventCommandMap/impl/EventCommandExecutor.as
C:/Users/MikeC/Desktop/as3hx/robotlegs2out/robotlegs/bender/extensions/eventcommandmap/impl/EventCommandExecutor.hx
C:/Users/MikeC/Desktop/as3hx/robotlegs2/src/robotlegs/bender/extensions/eventCommandMap/impl/EventCommandFactory.as
C:/Users/MikeC/Desktop/as3hx/robotlegs2out/robotlegs/bender/extensions/eventcommandmap/impl/EventCommandFactory.hx
C:/Users/MikeC/Desktop/as3hx/robotlegs2/src/robotlegs/bender/extensions/eventCommandMap/impl/EventCommandMap.as
C:/Users/MikeC/Desktop/as3hx/robotlegs2out/robotlegs/bender/extensions/eventcommandmap/impl/EventCommandMap.hx
C:/Users/MikeC/Desktop/as3hx/robotlegs2/src/robotlegs/bender/extensions/eventCommandMap/impl/EventCommandTrigger.as
Called from ? line 1
Called from Run.hx line 66
Called from Run.hx line 55
Called from Run.hx line 55
Called from Run.hx line 55
Called from Run.hx line 55
Called from Run.hx line 55
Called from Run.hx line 55
Called from Run.hx line 38
Called from C:Motion-TwinHaxe/std/neko/Lib.hx line 63
Called from Run.hx line 29
Called from as3hx/Parser.hx line 117
Called from as3hx/Parser.hx line 131
Called from as3hx/Parser.hx line 488
Called from as3hx/Parser.hx line 415
Called from as3hx/Parser.hx line 589
Called from as3hx/Parser.hx line 794
Called from as3hx/Parser.hx line 744
Called from as3hx/Parser.hx line 919
Called from as3hx/Parser.hx line 964
Called from as3hx/Parser.hx line 1106
Called from as3hx/Parser.hx line 1016
Called from as3hx/Parser.hx line 1075
Called from as3hx/Parser.hx line 1179
Called from as3hx/Parser.hx line 330
Called from as3hx/Parser.hx line 1003
Uncaught exception - In C:/Users/MikeC/Desktop/as3hx/robotlegs2/src/robotlegs/bender/extensions/eventCommandMap/impl/Eve
ntCommandTrigger.as(75) : Unexpected .

[/codesyntax]

It seems like as3hx is getting confused around this line in the AS3 source:

[codesyntax lang=”actionscript” lines=”normal”]

if (describeType(mapping.commandClass).factory.method.(@name == "execute").length() == 0)
				throw new Error("Command Class must expose an execute method");

[/codesyntax]

It looks like a bit of E4X is confusing the script. To solve this sort of problem I made a note of the location and file and just commented the offending line out. This allows as3hx to get past that particular snag. After going through this process a few times the project should be fully converted.

From there I setup a project in FlashDevelop and tried to compile. After fixing a few things that as3hx couldnt solve I came accross a rather major stumbling block.

RobotLegs2 unlike RL1 has a strong dependency on the dependency injection container SwiftSuspenders. So to get RL to compile I first need to port SwiftSupenders2.

So I repeated the process above but for SwiftSuspenders. Eventually this left me with a whole load of broken unit tests. Till Schneidereit the (rather splendid) author of SwiftSuspenders wrote a great number of unit tests for the library, which is one of the reasons why its so excellent. So I knew that to achieve a proper port all I need do is pass all those tests and I can then be confident that the code is solid.

After a few evenings of toil I managed to get 50 tests to pass in the Flash target. This is quite abit shy of the 160+ tests in the original AS3 version of the library, however a great many of those tests are not relevant to Haxe such as ArrayCollection tests, XML tests and DescribeType tests. I also decided for now to remove all of the event dispatching (and thus their tests) code from the library for now due to their dependency on the Flash platform. Despite this I think the 50 tests that do pass are probably representative of the core functionality of the library.

With the Flash target passing I indented to then move onto passing the tests in the other targets (JS, C++, php etc). I was hoping that with the flash part passing that they would all pass considering that im using the inbuilt haxe reflection methods not any platform specific reflection, but alas this was not to be the case. Starting with the JS target I started to get alot of errors on some of the basic Injector tests. After some digging in the compiled JS source I traced it back to an issue in the Meta Data generation for the @Inject tag on the JS target.

Unfortunately, I have run out of time on this little side project for now so am going to have to park it. I have uploaded the progress thus far to GitHub should anyone else wish to take up the mantle on the port:

https://github.com/mikecann/SwiftSuspendersHx
https://github.com/mikecann/RobotLegs2Hx

I had indented, once everything was passing, was to do a branch of the project and incorporate some features that only the Haxe language can support. Features such as proper generics and macros would bring some added awesome.