HTML5 Writing a game: Step 5

It’s all in the timing and that browser sounds different!

Click html5 rewrite of bouncing animals to try out the latest version.

As always, thanks for reading the updates on the HTML5 rewrite of bouncing animals. However, I need to start this post with an apology. I promised last time that I’d focus on keeping score and some baddies, but I got bogged down in a performance issue between browsers and I wanted to share my thoughts on that before continuing. In terms of game play, this post doesn’t add a lot of extra features, but in terms of consistent performance across browsers we’ve made significant improvements.

Initially I was using setInterval to create a game loop as shown below.

<br />
//Start/stop the game loop (and more importantly that annoying boinging!)<br />
function toggleGameplay() {<br />
	gameRunning = !gameRunning;<br />
	if(gameRunning) 	{<br />
		clearInterval(gameloopId);<br />
		gameloopId = setInterval(gameLoop, 10);<br />
	}<br />
	else<br />
	{<br />
		clearInterval(gameloopId);<br />
	}<br />
}<br />

In order to check the number of times the loop was actually being called, I decided to create a monitor for what was essentially my fps (frames per second) rate. By creating an interval of 1000msecs I would monitor the number of times the game loop had actually been called during that time period.

<br />
function startFPSCounter()<br />
{<br />
	setInterval(fps, 1000);<br />
}</p>
<p>//Update the display to show frames per second and reset ready for next count<br />
function fps()<br />
{<br />
	$(&quot;#fps&quot;).html(frameCount + &quot; fps&quot;);<br />
	frameCount=0;<br />
}<br />

During the gameLoop I would increment the value of the variable frameCount, thus giving me a total number of times the loop was called every second.

The setInterval time period for the game loop was 10msecs. Meaning I was hoping for near on 100 loops per second which on hindsight may have been a little ambitious depending on the browser and operating environment.

This is not a scientific test to compare browser speeds, but rather trying to establish what would be the best approach in terms of javascript timers when using HTML5 canvas to create an animation. However, the results of my first test where:

Using setInterval: 10msecs

Safari: average between 88-89 fps
Chrome: average between 99-100 fps
Firefox: average between 77-78 fps

So, with the exception of Chrome, it would seem that the browsers were getting saturated in terms of the their ability to actually call the loop and process the contents every 10msecs.

Then I realised, what if buy cialis online the browsers execution engines weren’t actually that accurate in terms the timers?

If that was the case, not only was the timer to execute the game loop inaccurate, but the timer checking how many times it was called would also give a false reading!

It was then that I discovered this article: http://blogs.sitepoint.com/2010/06/23/creating-accurate-timers-in-javascript/

For those that are interested in creating accurate timers in java script, I would recommend reading it. Although I note that one reply does call into question the idea, citing that many browsers force a minimum delay (usually 15msecs) and that the accuracy of this method of compensation isn’t that accurate. However, in the absence of any other method I decide to use this “auto compensating” method to attempt to create a consistent timing across browsers.

<br />
//Start game timer, i.e. setTimeout that calls itself taking into account the<br />
//actual real difference in time. </p>
<p>function startGameTimer()<br />
{<br />
	var start = new Date().getTime(),<br />
	time = 0;</p>
<p>	function timer()<br />
	{</p>
<p>		time += 15;<br />
		var diff = (new Date().getTime() - start) - time;<br />
		if(gameRunning)<br />
		{<br />
			gameLoop();<br />
			window.setTimeout(timer, (15 - diff));<br />
		}<br />
	}<br />
	window.setTimeout(timer, 15);<br />
}<br />

Following a number of tests across safari, chrome and firefox, it appeared that 15msecs was on average the best delay for consistency across browsers. The code above checks the time every time it calls setTimeout and attempts to compensate for any variation in accuracy by deducting the difference.

Also, the fps counter followed a similar mechanism attempting to ensure a consistent timing. This resulted in all browsers reporting a similar fps on the iMac.

<br />
function startFPSCounter()<br />
{<br />
   	var start = new Date().getTime(),<br />
		time = 0;<br />
	function instance()<br />
	{<br />
		time += 1000;<br />
		fps();</p>
<p>		var diff = (new Date().getTime() - start) - time;<br />
		window.setTimeout(instance, (1000 - diff));<br />
	}<br />
	window.setTimeout(instance, 1000);<br />
}<br />

setTimeout with auto compensating based on reported time from Date

Safari: average between 66 – 67 fps
Chrome: average between 66 – 67 fps
Firefox: average between 66 – 67 fps

With this generally slower, but consistent fps I increased the animals speed to +3 for a similar game play across all browsers.

In case you’re wondering the iPhone 3GS was not able to create a frame rate better than 9-10fps.

Audio for all

As mentioned in a previous post, Chrome supports only mp3 where as the others have included support for wav. So to ensure that the game plays sounds in all browsers I have now modified the loading of sounds to take into account he browser type and load the appropriate sound file.

<br />
var soundType = &quot;wav&quot;;</p>
<p>//change sound type based on browser (i.e. chrome)<br />
if(navigator.userAgent.toLowerCase().indexOf('chrome') &gt; -1)<br />
{<br />
	soundType = &quot;mp3&quot;;<br />
}</p>
<p>//Create and load sounds<br />
var boing1 = new Audio(&quot;./sounds/boing_1.&quot; + soundType);<br />
var boing2 = new Audio(&quot;./sounds/boing_2.&quot; + soundType);<br />
var boing3 = new Audio(&quot;./sounds/boing_3.&quot; + soundType);<br />
var boing4 = new Audio(&quot;./sounds/boing_4.&quot; + soundType);<br />
var boing5 = new Audio(&quot;./sounds/boing_5.&quot; + soundType);<br />
var awwwww = new Audio(&quot;./sounds/crowdgroan.&quot; + soundType);<br />
var collisionPrize = new Audio(&quot;./sounds/collisionPrize.&quot; + soundType);<br />
var collisionStarPrize = new Audio(&quot;./sounds/collisionStarPrize.&quot; + soundType);</p>
<p>

That concludes the changes done so far, next time I really will add some baddies and keep a score…. promise.

Click html5 rewrite of bouncing animals to try out the latest version.

Comments are closed.