Every time I sit down to write one of these posts, I feel like I am discouraging people from using CocoonJS, so let me state here at the top that I’m not doing that. Not purposely, anyway. I like CocoonJS. I think it serves a growing niche of developers who want to write in JavaScript, use HTML5, and then deploy to mobile systems. A niche served by a growing number of other services and software too.
It also has one major feature over things like PhoneGap or just using Cordova by itself: there’s no SDK to install or configure. CocoonJS definitely has its own share of problems, as I have tried to document, but that’s not one of them. You don’t have to add to your codebase in order to use it. However, you may have to take some of its known issues into account for your projects.
So, with that disclaimer of sorts out of the way, let me try to explain this latest journey.
After my last post discussing the Gamepad API, I finished and posted to GitHub a Phaser plugin that acts like the Gamepad object already part of Phaser, but takes the known gamepad issues, the increasing-index, unreliable timestamp, and at-rest large axis values, and works around them. It’s 90% of the Phaser.Gamepad code, but with a few functions changed to match those issues CocoonJS presents. I’ve been thinking of it as a patch for CocoonJS’ Gamepad API until the next version comes out and hopefully fixes most if not all of these things.
While I was working on this plugin, I was using the console to read values and test for things. I would have it log whatever section I was testing and then I would pull it up every time. I wasn’t really using the screen itself for anything other than a blank, black screen for the simple reason that Text support when using Phaser under CocoonJS is broken. Sort of. It’s, well, complicated. I think.
As best as I’ve been able to track down myself, the problem is in how Pixi.js (the library Phaser uses for all drawing) handles textures created from canvases used as pre-rendering buffers. Somewhere between creating a cached version of a texture with the written text and showing it, something happens. What exactly that something is, and if it is related to some other error related to drawing text on said created canvas, no one has quite figured out yet. It’s a known issue affecting both Pixi.js and Phaser at the moment.
Yesterday, I spent a few hours trying to track it down without much success. However, I did learn of two partial solutions.
The first uses the technique shown in the “TrueType Fonts” example on the demo page for CocoonJS.
(function(window, Phaser) { var game = new Phaser.Game(window.innerWidth, window.innerHeight, Phaser.CANVAS, '', {preload: preload, create: create, update: update}); function preload() {} function create() {} function update() { writeText("Updated text"); } function writeText(string) { var context = game.canvas.getContext('2d'); context.font = "45px arial"; context.textAlign = "left"; context.fillStyle = "#ffffff"; context.fillText(string, game.world.centerX, game.world.centerY); } })(window, Phaser);
Basically, if you are willing to re-implement your own Text object, you can. As long as you are writing directly to the underlining ‘screencanvas’ element, as this example does, your text will show up. In fact, you can use this as a quick solution if your project has very little text overall and you want to use different TrueType fonts directly.
However, it isn’t really an ideal solution to the problem. All this does is go around Phaser and allow you to make drawing context calls yourself.
While I was investigating Phaser’s 1.2 development branch source, though, I noticed this commit. It added in a RetroFont object that needed many more parameters to work, but got around the known issues of no XML support in CocoonJS and the problem of web fonts not showing up at the moment.
And, as luck would have it, this works. (And the ability to ‘tint’ the font does too, as a neat feature RetroFonts have.)
It’s slightly inconvenient, as it depends on fixed-width, sprite-based fonts, but it is also a major step forward on this problem. One I’ve seen across many different forums and blog posts at this point. Many people are struggling with this, believe me.
(Additional notes: 1) as the above image demonstrates, I’ve started to use my Elgato HD Game Cature device with my Ouya. It has made it super convenient to document error messages. Instead of typing them out or writing them down, now, I just take a screenshot that automatically records the timecode in its filename. It has sped up the process of debugging tremendously. 2) This thread has been where I’m trying to collect issues and solutions when using Phaser with CocoonJS.)