That said, think about CocoonJS as a kind of “browser”, which gives support for the HTML5 Canvas elements, websockets, XHR, audio tag… all of them customized for maximum performance and response time, but doesn’t give access to CSS, most of the document element out of the box objects and HTML markup in general.
The big question is: Why ?!?!?!?!?
Because after all, CocoonJS aims to execute Canvas games on mobile devices in full screen. That means, there’s no room for other elements but stacked canvas. And in a full screen environment, most of the functionality a browser offers is not needed. We don’t need scroll events, mouse events, etc. But admittedly, we need some layering of arbitrary markup language, and we are as of right now, actively working on it.
So, how do I get my games running accelerated to the bone in CocoonJS ?
The first thing to note, is that CocoonJS does not rely on an HTML file to run. This simple fact leads to some needs:
- Even though it is not absolutely needed, have all your JS source code in a single file.
- Instead of relying on an HTML defined canvas element, you must create it manually, either by calling new Canvas(); or document.createElement(“canvas”);
- Add manually created Canvas objects to the document as in a regular browser: document.body.appendChild(canvas);
Once this step is done, any Canvas based game should run at full accelerated speed.
ported adjusted Onslaught Defense (OD) to run inside CocoonJS
First of all, for those who use a module manager like require.js or any others. At the moment, CocoonJS doesn’t offer any support to the script tag. As I said previously, CocoonJS expects all your code in one single file. Some module managers like Impact engine’s, make a dependency resolution that doesn’t start injecting script files immediately. Somehow, it defers script injection until it has evaluated the whole file.
But with Onslaught Defense, which uses require.js, things didn’t work that straightforward. We had to patch require.js code to avoid script injection. After all, the whole Onslaught’s source code was already together in one file.
Patched code on require.js was:
- Dealing with document’s head and the calls for getElementsByTagName. Reason: no DOM support.
- getInteractiveScript: remove getElementByTagName(‘script’) block.
- req.checkReadyState function. Just return req.resourcesReady(true)
The way in which OD detected touch enabled was querying for
typeof window.ontouchstart !== "undefined". CocoonJS is touch enabled, so we substituted that check for: isTouch=true;.
OD was dealing with making a canvas object full screen if on mobile. In CocoonJS this feature is out of the box. So we patched the code to set
document.body.style.height. These are DOM related and not supported (nor needed on full screen mode). Also code related to canvas style and position was patched, since it isn’t needed.
For now on, the correct way of getting screen size is
window.innerHeight. To make your Canvas objects full screen, set
canvas.width= window.innerWidth; canvas.height= window.innerHeight.
One thing you must know about CocoonJS is that you don’t have to change your canvas size to make it run fullscreen. CocoonJS will up/down scale your canvas and have correct touch coordinates sent. You could choose how you’d like your canvas to be scaled, either keeping aspect ratio or not, and also if you want to have no blurring filter applied to the scaling operation, which comes handy for games relying on pixel art. Refer to the official CocoonJS Wiki pages to know how to control scale operations.
Since OD scales itself in the browser to conform the whole window size, we patched it from scaled canvas to game coordinates coordinate-transformation routines. Just comment two lines. Just commented two lines of code.
Localizing on-screen coordinates
Since in CocoonJS the canvas object takes full screen, there’s no need to deploy complex procedures traversing upwards the DOM hierarchy, adjusting with styles, etc. just to get the correct coordinate offset inside the canvas element. The canvas is always at 0,0 and touch events reported coordinates are already in Canvas space.
Modern browsers offer out of the box canvas-space coordinate values via
layerX, layerY or
offsetX, offsetY. CocoonJS is not a browser/WebView, and as multiplatform developers must derive procedures to get the correct canvas coordinate out of input events. Luckily for us, CocoonJS behaves like modern browsers as gives correct on-canvas coordinates out-of-the-box.
The only issue with the sound is that CocoonJS requires the method
load be called.
OD uses sound-sheets, which we don’t recommend at the moment. TBH we must improve the sound objects to be able to play sound-sheets.
The result, is a game running @250fps on iPhone 4S iOS 5.1 and @150fps on a Samsung Galaxy S2. The amount of tweaked lines was less than 30 and most of them were DOM related. The overall procedure took 2 hours until having a fully functional OD game deployed in CocoonJS launcher.
Yes, you’re right, sound-sheets are not running properly. Until the next CocoonJS launcher version, where they will.
Go, give it a try on the browser, and soon on natively on your mobile phones.