Making a Speedy HTML5 Game
by Sean Soria - April 17, 2012 at 8:00am

This is a guest post by Sean Soria of Gamzee, a leader in HTML5 game development. In this post, he describes the potential of creating a city build using HTML5, as well as the trial and tribulations and how you can avoid them.

Back when we started Gamzee, a lot of people in the game industry were down on HTML5. The hopeful ones said that HTML5 was the wave of the future, but it just wasn't stable or fast enough to make the big sort of 'Ville-type Flash games that dominate social gaming today. So what did we do? We set out to make a big, isometric game in HTML5. And not only would it run on Facebook on desktop Web, but it would also run on mobile Web, utilizing Facebook Platform. On all iOS devices and Android phones.

Pretty unambitious, right? Well, it’s what we did in making Skyscraper City -- an HTML5/node.JS game that runs on a single codebase and was built by a single team. As our first game as a new company, no less.

In case you don't want to read the rest of this blog post, the results of all that work is here (apps.facebook.com/skyscrapercity). And you can, indeed, play it on Facebook on the Web or on mobile on your iOS device or Android phone. Skyscraper City is a city-building game that combines the gameplay of social builders with the fun of Lego-style blocks. You can stack almost any city unit on top of any other to build towers, elaborate structures, or whatever you want.

What We Learned

Was it easy to make? Heck no.

What did we learn? Here are the highlights.

Way more people play the game on mobile devices than we expected

One of the reasons we wanted to make a cross-platform HTML5 game is because we're all gamers. I play CityVille, and I want to check into my city on my phone while I'm out and about. Zynga did launch CityVille Hometown, and I can download that if I've got an iPhone or and Android phone, but it's not the same game and it's not the same city. Our game is truly cross-platform; you can play on your computer, your tablet, and your mobile device and maintain your progress on all those devices.

That's how we thought most people would play the game, too -- mostly playing on a computer, then continuing on a tablet or phone while they’re not at their computers. But there are more people playing the game on the iPod Touch or the iPad than there are on a Mac, for example. And way more Android phone users playing than any of those devices combined.

Had we known that at the start, we could have spent more time optimizing mobile and less on Mac browsers. While we built with mobile in mind, we envisioned mobile as a secondary play environment. We recommend that game developers making cross-platform focus on delivering a great mobile experience as their primary goal.

You have to do a lot of experimentation

We started with the idea that we'd use Canvas (yay, HTML5) to render our game. That worked great on desktops -- no performance issues. But on an iPhone 3GS, the performance was horrid (rendering less than 5 frames per second when we were working on the game; performance has improved a lot with the release of iOS 5.0).

So we had to create another render engine. And another one. And another one. Until we have the one we use now (a DOM renderer), that works pretty well on most devices. The DOM renderer uses CSS animations, creating and animating in divs. It also allows us to use a little kludge, using fake 3D CSS transforms on our 2D images in order to trigger hardware acceleration on mobile (which gives us a little boost in performance).

Some things you're just not going to be able to do well

Sound performance in HTML5 is still pretty iffy. The expectation in game development is that you’ll have mutliple sounds that can play in response to cues in the game and gamer inputs. Despite a lot of experimentation, it's hard to get low-latency cued up sound (i.e. a sound that reliably plays in response to a game or user action) and impossible to get multitracking (sound and music playing at the same time, for example) on most mobile devices. So we opted for sound and music on desktop and just music on mobile Web.

Similarly, a simple trick to speed up performance on the DOM is fake 3D transforms on your CSS. That triggers hardware acceleration on most mobile devices, resulting in better performance than Canvas, for example.

For some reason, this doesn’t work on some Android phones, like Samsung’s Galaxy S2. As a result, you don’t get a performance boost there.

Here’s code that we used to trigger 3D transforms. And, as a bonus, we’re also showing you how we prevent the user from selecting big chunks of text/graphics inadvertently and how we prevent the game from displaying the text cursor occasionally (both fixes help make the game feel more like a native app than a Web app).

/******************************/
/* Makes screen non-selectable and prevents text cursor from displaying */
/******************************/
div {
    margin: 0;
    padding: 0;
    -moz-user-select: -moz-none;
    -khtml-user-select: none;
    -webkit-user-select: none;
    /*3D transform */
    -webkit-transform: scale3d(1, 1, 1);
    -o-user-select: none;
    user-select: none;
}

If you're going cross-platform, you have to design that from the ground up

We wanted to achieve as close to 1:1 parity as we could on the mobile experience as the desktop Web experience. So that meant turning off pinch to zoom on phones, not having rollover item/drop pickups on the Web version of the game, and figuring out ways to implement rollovers on mobile (ours are either activated off of a button or by holding down your finger on the item in question).

Something like Cityville wouldn't work on mobile, at least not without substantially changing the game experience, because it wasn't designed around mobile screens. The menus are too large and complicated, and there's too much going on in a city to easily show on a (relatively) tiny iPhone screen (hence the separate app Cityville Hometown for iOS and Android rather than an integrated experience).

Don't do stacking(!)

One of the cool features of our game is that ability to stack I mentioned earlier. It's really fun to make a giant robot in your city or construct an odd, stepped reverse pyramid supported by four thin columns.

Unfortunately, stacking presents a host of issues on mobile. People with less than slender fingers sometimes have a hard time accurately picking what they want to click on. And, like Flash, render times increase the more objects you're drawing on screen.

We start our players out with a 10x10 city grid. You can get that up to 11 stories tall. If you slapped down 1-tile buildings that high, that's 1,100 buildings. That's a lot of buildings to render. (And that's before the expansions we just added that let you quadruple the size of your grid). So while stacking is very neat, it can bite you in the butt with a very large city, making the game take a while to load (up to a minute-plus on some mobile devices; the problem isn’t noticeable on desktop due to larger processing power). We’re making optimzations to how the game renders large amounts of objects. But we would have been better served by realizing this in advance and coming up with another gameplay feature instead of stacking.

Love CSS

You'd better be good at CSS, because getting a game working on all major browsers on desktop Web and Android phones and all iOS devices requires a lot of the stuff. We have one Web Developer whose whole job is focusing on that, building out menus that will dynamically size for various mobile devices and master versions for Web and tablet. One of the axioms of video game design is that it's 50% menu work. HTML5 cross-platform games are probably 50% CSS work.

Areas of focus and useful tools

So what did we take away from our experience?

  • We validated that you can make a cool, rich isometric game in HTML5 and have it be cross-platform.
  • We learned that if people can play a game on any device, a lot of them are going to do it primarily on mobile or tablet.
  • We learned that HTML5 cross-platform games require a lot of experimentation.
  • We learned that as great as HTML5 is, some things still aren't quite there yet;
  • That designing a cross-platform experience means you need to think about the user experience on all devices from the ground up (in your game design);
  • That you shouldn't have a game on mobile that does a lot of stacking or overdrawing;
  • And that you'd better love CSS and be good at it.

Hopefully you learned something, and hopefully you'll enjoy our game.

And for those of you who read through to the end, here are a few things that made our lives easier as we developed a cross-platform HTML5 game on Facebook Platform.

1) Viewporter. https://github.com/zynga/viewporter. Zynga’s open-source code allows you to get screen size on any device and to scale your game to match. It saves a lot of time from writing it yourself (we know because we’ve used Viewporter and written our own).

2) Weinre. http://phonegap.github.com/weinre/. A remote debugger that works like Web Inspector, but on mobile devices. A real lifesaver when it comes to tracking down console errors on devices like iPhones and iPads.

3) JQuery. http://jquery.com/. Why write your own code if you can leverage a library? For things like text animations, JQuery’s very solid. We’ve made a few modifications, and JQuery Mobile now exists, which is better optimized for mobile devices, but JQuery gave us a huge headstart.

4) node.JS. http://nodejs.org/. When you’re working in Javascript, it saves a lot of time and effort when you can have your client code and server code match as closely as possible. node.JS also scales remarkably well when acting as a game server.

Building a game using HTML5? Leave your feedback below!