Pushing the Boundaries of HTML5 Gaming: Jitterbugs

For many developers, the acid test of whether HTML5 is ready for primetime is gaming. Few other scenarios push a technology as far: with demands for low-latency input, intensive rendering of animated graphical content, layered audio, full-screen display, and a consistent framerate despite inconsistent workloads.

Given the support for full hardware acceleration in IE9, we were eager to see how far we could push the platform. Until now, there has not been an impressive selection of HTML5 games, or rather, the games that are there around are limited in their level of interactivity. For instance, the most highly rated games on Chrome Experiments at the time of writing are implementations of Solitaire and Tetris, games that were well within the capabilities of Windows 3.1.

We felt the web deserved better, and so we commissioned one of the world’s leading rich internet application designers, Cynergy, to see what they could put together in a few short weeks with Internet Explorer 9 beta. The game they put together, Jitterbugs, is in my opinion the most intensive HTML5 game available so far, and it certainly shows off why we need hardware acceleration in our browsers if they are to serve us well as a foundation for client application development.

image

Jitterbugs is (by any definition), an extensive example of HTML5 usage, with in particular both Canvas 2D and audio features used to great effect within the game. Indeed, the primary element of the DOM tree is a large (1100x800) canvas on which the game surface is rendered. There’s very little HTML itself in the program – it’s primarily used for preloading audio assets and creating the frame for the game, with JavaScript used to handle the canvas rendering and interactions, as you’d expect.

In the game, the objective is to use your mouse (or a touchscreen if you have one at your disposal) to circle two or more identically-colored bugs, which are “jittering” around the screen at a fairly slow pace. The faster you net the bugs, the more points you score. If you complete an entire screen, you get a nice win animation before the next level, where there are more bugs than previously. Over a few levels, the intensity builds up – you need to start scoring combos by netting the same colored bug repeatedly, which slows down the jittering and makes it easier to capture more of them. At the end, you can tweet your final grand score as a challenge to others!

image

Inside the Code

Turning to the JavaScript for a moment, Jitterbugs is very well-structured and surprisingly short – the entire game is less than 2,500 lines of code, spread across four files (audio.js, controller.js, gameLogic.js and band.js), which I’ll briefly describe.

audio.js contains functions that are used to transition between individual layers of sound as well as reset the audio. When you first begin a level, the sound is silent, and then as you start to net bugs the various instruments begin to play, gradually the bassist and other instruments join in, and by the time you get to the end, the entire band is swinging.

The audio files themselves are loaded in HTML, for instance:

 <audio id="s0layer1" preload="preload">
   <source src="audio/s0layer1.mp3" type="audio/mp3" />
 </audio>
  
 <audio id="s0layer2" preload="preload">
   <source src="audio/s0layer2.mp3" type="audio/mp3" />
 </audio>
  
 <audio id="s0layer3" preload="preload">
   <source src="audio/s0layer3.mp3" type="audio/mp3" />
 </audio>

Note the use of the preload attribute, which hints to the browser that the files can be loaded asynchronously as resource availability permits.

controller.js is responsible for the flow of the game: it handles drawing things like the preloader screen, animating the “stage” (e.g. the windmill and tower signs in the odd-numbered levels) and setting up event listeners for the mouse events. It also contains the game loop itself, which looks like this:

 function gameLoop() {
   canvasRoot.width = STAGE_WIDTH;
   updateBkg();
   updateStage();
   updateGameboard();
   updateResults();    
   updateBugs();
   updateGameUX();
   updateBand();
   updateFrame();
   updateAudio();
 }

The game loop is triggered with a call to setInterval, a JavaScript method which calls the function every 20ms:

 masterLoop = setInterval(gameLoop,20);

This ensures the UI itself is drawn at a constant 50fps rate (assuming the browser has finished drawing the previous frame and handling any associated events by the time the interval has completed.

gameLogic.js contains most of the core game itself, in terms of displaying the various sprites and managing interactions between them (e.g. lassoing the bugs). The interesting piece to note here is how the images are drawn on the screen with a given rotation. Here’s a simplified portion of the code: for drawing the bugs on-screen:

 for (var i = 0; i < introBugs.length; i++) {
   temp = introBugs[i];
   temp.x += temp.vx;
   temp.y += temp.vy;
   temp.vy += Math.random();
   temp.vx += Math.random();
  
   ctxRoot.save();
   ctxRoot.translate(temp.x, temp.y);
   ctxRoot.rotate(Math.atan2(temp.vy, temp.vx));
   ctxRoot.drawImage(bugImages[temp.imgIndex], -.5*temp.width, 
     -.5*temp.height, temp.width, temp.height);
   ctxRoot.restore();
 }

The important thing to note is that it’s the canvas being rotated, rather than the graphical elements themselves. The process is analogous to drawing a stick figure at an angle on a piece of paper, where you’d likely rotate the paper and then draw the figure upright at that angle before returning the piece of paper to its original position. In the same way, here we save the position of the context with (ctxRoot.save), translate and rotate the context (ctxRoot.translate / ctxRoot.rotate), draw the image (ctxRoot.drawImage), and then restore the context to its saved position (ctxRoot.restore).

This is a little counter-intuitive: as Rick, the developer notes, there are no good tutorials currently out there that explain this, how to do it, or even why it works. Rotating the drawing context isn’t an obvious solution, particularly to developers who come from a Flash or Silverlight world.

Lastly, band.js contains the functions that draw and animate the band that appear at the bottom of the screen. It wasn’t until I looked through the code for the first time that I realized that the band had two different outfits, which alternate with each level along with the background imagery and music. Each band member is composed out of a number of limbs – left and right arms, a body, and the instrument itself, which are drawn on the canvas in the same manner as the bugs, listed above.

Fun Trivia

  • This project didn’t always seem to be going in the right direction. Having submitted a great concept for an ambient touch-based musical experiment, Rick sent me a mail a couple of weeks in to say that he’d got a new idea for the project of building a game that involved lassoing bugs while some birds sang a song in French. There were a few sleepless nights on both sides because this sounded too surreal to be appealing to a broad audience. Fortunately, this is one of those cases where if you have a good designer you should just trust them rather than trying to manage by committee – I’m tremendously pleased by the final result, even if I had no idea how it would turn out four weeks prior to the beta launch.
  • Cynergy worked with two award winning musicians to create the fantastic music for the game. They had a great write up about it at TBD (the local news site for Washington DC, where Cynergy are based). To our collective amusement, the "girl" singing the songs is actually one of the two male artists (Kokayi) whose voice was modified in the studio by the other artist (DJ Eurok).
  • The game was originally designed with SVG, because we hadn’t at that time released a version of IE9 that supported the Canvas 2D APIs. Over a period of time, the code got gradually rewritten until it was entirely using Canvas. (I’ll feature another project in a little while that is SVG-centric, to redress the balance.)

Outcomes

We’re really happy with the project – I think it’s a really fun game that pushes HTML5 far further than I imagined it could go. When I first showed it to some of the Program Managers responsible for Canvas and other parts of the rendering engine, they were genuinely astonished that HTML5 and what they’d built could handle this kind of intensive experience. And without full hardware acceleration, this game just doesn’t work well at all – try it in another browser to see that in practice. It’s not because Jitterbugs does anything to optimize for IE itself – it’s just because this kind of experience needs to harness the full underlying power of the PC.

The other point of interest is that this was the first HTML5 project for Rick Barraza, the designer / developer responsible for this game. As he commented in an interview with the marketing team:

“I had already dismissed HTML5 as still not being good enough. If it wasn’t for a commission by my company to spend a couple weeks and deep dive into the Platform Preview, I probably wouldn’t have tried it. I think a lot of interactive media people like myself may be in that same boat right now. I had seen other people’s work with Canvas in other browsers, and I figured IE9 would be more of the same thing. But I’ll openly admit that I was premature in that. Once the Platform Previews came out that supported Canvas and also, more importantly, showed off the true power of full hardware acceleration, everything changed for me. I was finally able to dive deeply into HTML5 and start creating things that were on par with what I do in the other interactive media languages I work with. It was really impressive and now I’m very glad that I’ve had this chance to upgrade my skill set so quickly. My toolbox just got bigger.”

This is great news if you care about having a powerful, mainstream HTML5 platform. May your toolbox also get bigger!