In the installment of this three-part series, seasoned console developers, formerly of Criterion, describe the process of moving to HTML5 development, covering a vast array of essentials. Don't miss Part 1 and Part 2.
In this final installment, we continue our description of HTML5 and related interfaces for functionality relevant to games, and look at strategies for dealing with important issues such as resource loading and security. We then give a brief overview of the state of HTML5 for mobile devices and conclude with some of the reasons we feel developers should already be targeting HTML5 for high-end games.
Networking - Web Sockets
The WebSocket API allows a full-duplex permanent communication between the browser and a server. WebSocket connections start as standard HTTP connections and then get upgraded to the new protocol, which should make WebSocket connections reliable across proxies and firewalls. We found the API very simple to use. Setting a couple of callbacks gives you easy access to a full-duplex communication.
WebSocket connections use TCP as the transport mechanism, which makes it reliable: messages are guaranteed to arrive, and to do so in the order they were sent (unless of course the connection breaks).
As with any other TCP connection, we found latency to be an issue if the browser, server or some Internet node in between tries to optimize for bandwidth instead of optimizing for latency. Some clients or servers will employ Nagle's algorithm to maximize the amount of data they send per packet, and this will introduce delays.
The WebSocket API does not allow connecting directly from one browser to another. One must always connect to a WebSocket server.
The long definition process of the specification created an unfortunate situation where different browsers supported different versions of the protocol, and some changed from one version to another. This means that your servers will need to support several versions of the protocol in order to handle all clients that may try to connect.
As part of the online infrastructure for games, Turbulenz provides a multiplayer server for clients to communicate with each other. This is used in the multiplayer version of Score Rush to synchronize up to four players in a single session.
As not all browsers will support WebSockets, there are emulation libraries such as SockJS which implement a similar API using other mechanisms. These other mechanisms generally require specific server-side support, and the latency of the different fallbacks is likely to be higher than when using WebSockets. The Turbulenz plugin provides WebSocket support for browsers that do not natively support the API.
The Audio Element
The audio element provides support for loading and playing sound files. It's addition to the HTML standard created a good opportunity for sound in games without using a plugin. Unfortunately, the quality of the early implementations made it unsuitable for anything beyond basic use cases. For example, Firefox did not support the loop property which required code to figure out, via events, when a sound finished in order to restart it. Even then, the silence between the end of the playback and the restart was easily noticed.
Some workarounds required two audio objects created from the same source file, one of them paused and ready to start playing as quickly as possible when the other one finished. This ping-pong between the two sounds performed better than restarting a single one, but added complexity to the code and was a waste of resources for games with complex sound scenes. Other implementations had issues when playing several sounds at the same time, with stuttering and general low quality output. The situation now has improved, but there are still many of the older browsers active in the wild.
The lack of support for a standard file format across all browsers makes the new API difficult to use. Internet Explorer only supports MP3 files, Safari only supports Wav and MP3 files, Firefox only supports Wav and Ogg files. Chrome seems the only browser that supports all three of these formats. This means that in practice sound files should be encoded as both MP3 and Ogg formats to cover all browsers.
The Web Audio API provides better support for high quality sound. Loosely based on OpenAL, it provides accurately timed playback of sound sources, 3D sound, filters and complex channel manipulation. It is a much more suitable solution for games than the audio element, but unfortunately at the time of writing only Chrome supports it.
Unlike OpenAL, the API does not yet support relative 3D sound sources, requiring constant update of the source location to follow the listener around.
Turbulenz has designed a 3D sound API closely following the OpenAL specification and we provide implementation of this API for several different backends: Web Audio, audio element (simulated 3D sound by setting the sound volume based on distance to listener) and if the browser does not provide support for either then our plugin directly implements the API.
Threading and Parallelism
The Web Workers API provides support for running scripts in the background, independently of any foreground page script. These background scripts communicate with the foreground one via messages, and the browser will copy the contents of those messages to avoid shared data issues. Therefore sending large amounts of data can have a performance cost. Future browser versions could support a form of zero-copy when using an ArrayBuffer as the message: one script writes to it, the other reads from it.
As described by the API specification, browsers expect workers to be long-lived. They have a high start-up performance cost, and a high per-instance memory cost.
To create a Worker a URL must be specified for the location of the script code the Worker will execute, although there are ways to create Workers from inlined code.
If the browser does not support Web Workers then its functionality will have to be emulated.
Currently only third party browser plugins support this API. None of the browsers support it natively.
The Mouse Lock API overcomes another of the traditional limitations of browser gaming, namely that if the mouse cursor leaves the browser window, the game stops receiving mouse movement events (effectively making it impossible to fully implement traditional first-person shooter camera controls -- the player must keep dragging the mouse back to the browser). This API decouples the visual position of the mouse cursor from the movement information from the mouse hardware.
Security concerns will also limit which code can lock the mouse and when, to avoid malign code controlling the mouse without the user's consent.
Unfortunately, this API still has limited support on modern browsers, and when supported, sometimes it only applies to fullscreen mode.
Support for input events from gaming-specific input devices such as gamepads, joysticks, driving wheels, pedals, and accelerometers is provided by the Gamepad API. The interface is similar to that already provided for keyboard and mouse, but still has only very limited support among modern browsers.
The Turbulenz plugin provides support for input events coming from gamepads and joysticks.