Tuesday, September 18, 2012

ImpactJS CocoonJS and Scoreoid working together on Android

Want to know how I stitched together a middleware data provider, an html5 game framework and a html5 JavaScript accelerator for android?

What is ImpactJS?

ImpactJS is a framework for creating HTML5 games really fast with JavaScript. It has a great community of developers and they are very responsive and helpful.


What is CocoonJS?

CocoonJS is a platform that lets you develop and accelerate HTML5 games on both the iPhone and Android it is being updated regularly. The demo sources that Ludei offers to use with the launcher app are well worth taking a look at before diving in.


What is Scoreoid?

Scoreoid is a non-restrictive server platform for games. It has been developed by developers and has many intuitive features. It lets you worry more about making your game and less about the middleware you need to handling user experiences like leaderboards, inventory, progress and other statistics. 


So now you have a framework to make your game, a way to put that game on a mobile device running android and a middleware system to send, fetch and store data. Should be easy to setup right?

Read this great post by about planning for mobile BEFORE designing and coding your game. It is worth every word.


Understand what Ludei is doing and your new limitations in impactJS

Ludei is taking your impactJS game and migrating it to the android. It is more than just running it inside a webpage in an App which means that you don't get all the bells and whistles that you normally would have if you were running the game on a webpage. They are working agressivly to add in features like getElementById but in the mean time you must get creative.

edit: after writing this I have used getElementById to remove ui elements so it is working, however if impactjs attempts to reference and element by id such as bindtouch(); it still throws an error.

Your first stumbling block is going to be creating your Canvas. In impactJS you simply reference the id. Now you cannot so you must create the canvas first and then reference it afterwards.

Like so:
var c = document.createElement('canvas');
c.id = 'canvas';
document.body.appendChild(c);
ig.main( '#canvas', MyGame, 60, window.innerWidth/2, window.innerHeight/2, 2 );

Not having getElementById means that bindTouch() [here] is not going to work for you. Instead I have found that adding my touch controls as images and using CocoonJS' addEventListener() to be an easy way to get touch events into impact via Cocoon.

Note that touch events are different then binding mouse1 with ig.input.bind(). Just binding mouse1 will not let you multi-touch. In other words you are not going to run and jump at the same time with mouse1.

Here is a sample of me placing an image after my canvas and adding a CocoonJS listener for touchstart


var c = document.createElement('canvas');
c.id = 'canvas';
document.body.appendChild(c);
ig.main( '#canvas', MyGame, 60, window.innerWidth/2, window.innerHeight/2, 2 );
var d = document.createElement('img');
d.id= 'menu';
d.src='menu_btn.png';
d.style.position='absolute';
d.style.bottom="0"
d.style.right="0";
d.addEventListener("touchstart", function()
{
    //IMPACT EVENT CODE HERE
});

edit: I have also created elements and bound touch events during the init extension of an impact entity. I have also removed elements from the cocoonjs dom during the init and update of entities. There will be an in depth post on this soon!

There may be much better ways to do this if you know of any comment. I also know that Ludei is working to add getElementById to the launcher soon and then impacts bindTouch() should work making this whole process better

Want to get Scoreoid calls out with ajax inside CocoonJS?

Enter the webview, your new best friend.

By creating a CocoonJS webview page and loading the path you can initialize a full DOM behind the scenes of your game. This allows you to reference outside functions from inside your game using CocoonJS' forward and also send data back into your game from the webview.

If you open the Ludei demo webview you will find this (below) and you should have no problem modding it for your own uses. If you just omit the adding the 'show' event then the webview should load and be available in the background I think, I am testing this tonight soon :)


someObject.addEventListener("touchstart", function()
{
    ext.IDTK_APP.makeCall("forward", "ext.IDTK_APP.makeCall('show',0,0," + window.innerWidth/2 + "," + window.innerHeight + ");");
});

ext.IDTK_APP.addEventListener("forwardpageload", function() 
{
    ext.IDTK_APP.makeCall("forward", "ext.IDTK_APP.makeCall('show',0,0," + window.innerWidth/2 + "," + window.innerHeight + ");");
});

ext.IDTK_APP.makeCall("forward", "ext.IDTK_APP.makeCall('loadPath', 'webview/wb_trans.html')");


With the webview exposed you can now call your functions to send and fetch data using ajax from a scoreoid proxy you are hosting. Or you can setup your own webservices/data methods and write functions to access them from the webview.

I spent a lot of time trial and error getting these things to play nice with each other. If you know of any improvements or see something that needs to be fixed your comments are greatly appreciated.

thanks to everyone that joined in on the impactjs forums, irc, and twitter to get some of these wrinkles out.

-TigerJ
https://twitter.com/stalkjimmy