Historically, running a game within the browser has been almost impossible without a plugin because timing has not be exactly reliable.
The traditional approach was using the setTimeout method, but this resulted in problems in that the Browser implementations could not always successfully notify code based on the poll interval. This is a bad experience, since the developer has been given the expectation that a timer can fire ‘on-time’.
Enter RequestAnimationFrame
The HTML5 spec has introduced the requestAnimationFrame api, which is really the browser admitting that it really doesn’t know when it will be able to transfer control back to your javascript application. To aid even further in the effort, the callback registered in the requestAnimationFrame call is even given a systemically-accurate time-stamp in order to track the time delta between intervals. Although this is a move in the right direction, not all browsers support this api yet.Designing a Reliable Game Clock
To run a game, we need the fastest possible callback intervals to trigger our game loop. But, the HTML5 Spec is admission that a interval based callback just isn’t possible, since the browser has a ton of other work to do outside of your applications tab. That means, we need to forget about scheduling and start responding to time shifts. The game Clock will have to have a few key featuresCan support HTML5′s requestAnimationFrame
Can fallback to setTimeout at an aggressive interval
Can track interval differentials to extreme accuracy across all callback implementations
Can be instance-based so we can have many observers
Should not hold onto subscriber scope (to avoid memory leaks)
The Shim Layer
For starters, we could override the default HTML5 api to support fallbacks to setTimeout. This way, we can code against the HTML5 spec and just let browser support roll-in when it can.see Paul Irish’s article on the requestAnimationFrame API and recommend usage
This approach is pretty common and is attractive in that you can just register your call back with the new requestAnimFrame method. But, it needs to be extended a bit to allow diff tracking and allow us to terminate the interval instances in the case we want to manage the clock’s lifecyle (start/stop).
Clock Bits from the ThreeOneFour Game Architecture
Below is a clock implementation I wrote for the ThreeOneFour source that should meet all of our needs: see Building Strong Types for details about the class definition used in this sample
Things to Note in this Implementation
- Shim Layer still present to map the requestAnimFrame to all of the specific browser implementations
- next requestAnimationFrame registration occurs before working the callback
- The fail-over timeout implementation is schedule at 1ms
Usage
Here is an example of instancing of the Clock. Based on this implementation, the time differential in MS will be passed to subscribers no matter the browser. Note that we should test our clock implementation for closure-based memory leaks, since game-clocks are typically instances used through the tiers of a game via the Cross Cutting Patternsee Snagging Javascript Memory Leaks for more details about instance disposal