<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>21st Century game development</title>
	<atom:link href="http://astronautz.com/wordpress/feed/" rel="self" type="application/rss+xml" />
	<link>http://astronautz.com/wordpress</link>
	<description>iPhone Game Development</description>
	<lastBuildDate>Sat, 17 Mar 2012 14:33:05 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Why PNGs are a poor choice for games</title>
		<link>http://astronautz.com/wordpress/why-pngs-are-a-poor-choice-for-games/</link>
		<comments>http://astronautz.com/wordpress/why-pngs-are-a-poor-choice-for-games/#comments</comments>
		<pubDate>Sun, 26 Feb 2012 14:05:43 +0000</pubDate>
		<dc:creator>Ed Welch</dc:creator>
				<category><![CDATA[graphics]]></category>
		<category><![CDATA[game development]]></category>
		<category><![CDATA[png]]></category>

		<guid isPermaLink="false">http://astronautz.com/wordpress/?p=751</guid>
		<description><![CDATA[Optimising game load time is something often neglected by developers, but still it is quite important. It&#8217;s quite tedious for players waiting several seconds each time a new level loads. Quite a lot of this load time is caused by &#8230; <a href="http://astronautz.com/wordpress/why-pngs-are-a-poor-choice-for-games/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Optimising game load time is something often neglected by developers, but still it is quite important. It&#8217;s quite tedious for players waiting several seconds each time a new level loads. Quite a lot of this load time is caused by the PNG format.</p>
<p>Recently, in the course of releasing our <a href="http://www.codeproject.com/Articles/330742/Texture-Atlas-Maker">Texture Atlas Maker</a> tool, I benchmarked the loading time of various PNG and Targa images on both PC and iPhone platforms. The images were loaded via libpng on the PC and via UIImage on the iPhone. The image tested is a complex 1024&#215;1024 texture with alpha transparency.</p>
<table border="1" style="white-space:nowrap">
<tr>
<th></th>
<th>Load iPhone</th>
<th>Load PC</th>
<th>size</th>
<th>Size Zipped</th>
</tr>
<tr>
<th>32-bit RLE Targa</th>
<td>87 ms</td>
<td>8 ms</td>
<td>1.79 MB</td>
<td>1.10 MB</td>
</tr>
<tr>
<th>PNG uncompressed</th>
<td>350 ms</td>
<td>32 ms</td>
<td>4.00 MB</td>
<td>1.14 MB</td>
</tr>
<tr>
<th>PNG no filter</th>
<td>379 ms</td>
<td>59 ms</td>
<td>1.13 MB</td>
<td>1.12 MB</td>
</tr>
<tr>
<th>PNG adaptive filter</th>
<td>529 ms</td>
<td>129 ms</td>
<td>1.01 MB</td>
<td>1.01 MB</td>
</tr>
</table>
<p>Targa uses a much simpler method of compression &#8211; run-length encoding &#8211; and hence is much faster to decode. As you can see from the chart it&#8217;s 5 times faster to load on the iPhone and 16 times faster on the PC, while being 77% larger. While the size difference is important for a web page, in a game it&#8217;s pretty inconsequential. Disk space is cheap, and a few kilobytes more won&#8217;t make much of a difference. Besides that games are normally distributed in zipped form and when the images are zipped they are all about the same size. </p>
<p>These benchmarks highlighted another interesting fact. PNGs are compressed in two phases, first a filtering phase, then it&#8217;s compressed by zlib. Most programs, including Photoshop and the Gimp, use adaptive filtering. The filter phase results in better PNG compression, but it also results in a much slower decode time. PNGs with adaptive, or paeth filtering load 40% slower on the iPhone, and 118% slower on the PC. </p>
<p>Using <a href="http://advsys.net/ken/utils.htm">PNGOUT</a> the filtering can be easily removed. In fact, <strong>we can potentially double the load speed of a game simply by calling this line on all the PNGs:</strong><br />
<pre><code>
pngout /f0 /force 
</code></pre></p>
]]></content:encoded>
			<wfw:commentRss>http://astronautz.com/wordpress/why-pngs-are-a-poor-choice-for-games/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The real reason Firefox lost to Chrome: Firefox 4</title>
		<link>http://astronautz.com/wordpress/the-real-reason-firefox-lost-to-chrome-firefox-4/</link>
		<comments>http://astronautz.com/wordpress/the-real-reason-firefox-lost-to-chrome-firefox-4/#comments</comments>
		<pubDate>Fri, 20 Jan 2012 17:31:48 +0000</pubDate>
		<dc:creator>Ed Welch</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[browser wars]]></category>
		<category><![CDATA[browsers]]></category>
		<category><![CDATA[Chrome]]></category>
		<category><![CDATA[firefox]]></category>

		<guid isPermaLink="false">http://astronautz.com/wordpress/?p=739</guid>
		<description><![CDATA[In November last year Chrome overtook Firefox in market share for the first time. Part of the reason was the declining IE user base and the simplicity of the Chrome user interface, but what people don&#8217;t realise is that the &#8230; <a href="http://astronautz.com/wordpress/the-real-reason-firefox-lost-to-chrome-firefox-4/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>In November last year Chrome overtook Firefox in market share for the first time. Part of the reason was the declining IE user base and the simplicity of the Chrome user interface, but what people don&#8217;t realise is that the release of Firefox 4 played a large part in it.<br />
Firefox 4 was a major new release and came with a brand new Javascript engine and HTML5 parser. Unfortunately, these new features came with <a href="http://blog.mozilla.com/nnethercote/2012/01/17/notes-on-reducing-firefoxs-memory-consumption/">major memory leaks and performance bugs</a>. The result was that if you used Firefox 4 for an extended period of time the browser would eventually become unresponsive, making it virtually unusable.<br />
The performance bugs were either ignored, or not considered important by the Mozilla development team, so it wasn&#8217;t until the release Firefox 7 &#8211; 5 months later &#8211; that they were <a href="http://www.gadgetvenue.com/firefox-7-to-use-up-to-50-percent-less-memory-08114900/">properly resolved</a>.<br />
<a href="http://astronautz.com/wordpress/wp-content/uploads/2012/01/trends.jpg"><img src="http://astronautz.com/wordpress/wp-content/uploads/2012/01/trends.jpg" alt="" title="trends" width="841" height="475" class="aligncenter size-full wp-image-740" /></a><br />
The outcome was that users switched browsers in frustration. From the graph you can see from the release of Firefox 4 at end of March there is a notable downward trend.<br />
Ironically, Firefox 4 was being marketed as being much faster, because of it&#8217;s new Javascript engine. This made the users even more frustrated as they were experiencing the very opposite to what they were being promised and there was a loss of trust.<br />
Eventually, the <a href="https://wiki.mozilla.org/Performance/MemShrink">MemShrink</a> team resolved the performance bugs introduced by Firefox 4, but by that time it was too late. Once you start a trend like this it&#8217;s very hard to reverse it. Users that switched to Chrome are unlikely to return, as Chrome offers basically the same features. </p>
]]></content:encoded>
			<wfw:commentRss>http://astronautz.com/wordpress/the-real-reason-firefox-lost-to-chrome-firefox-4/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>HTML5 animation using a texture atlas</title>
		<link>http://astronautz.com/wordpress/html5-animation-using-texture-atlas/</link>
		<comments>http://astronautz.com/wordpress/html5-animation-using-texture-atlas/#comments</comments>
		<pubDate>Sun, 15 Jan 2012 20:38:51 +0000</pubDate>
		<dc:creator>Ed Welch</dc:creator>
				<category><![CDATA[CodeProject]]></category>
		<category><![CDATA[web development]]></category>
		<category><![CDATA[canvas]]></category>
		<category><![CDATA[html5]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://astronautz.com/wordpress/?p=693</guid>
		<description><![CDATA[Your browser has no canvas control support! In last week&#8217;s tutorial we used the canvas control to make a character&#8217;s eyes follow the mouse. This week Nelly the elephant is back again. This time we will add some animations and &#8230; <a href="http://astronautz.com/wordpress/html5-animation-using-texture-atlas/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><script type="text/javascript" src="http://astronautz.com/wordpress/animateNelly.js"></script><br />
<canvas width="160" height="160" style="float: left; margin: 10px;" id="nelly"><em>Your browser has no canvas control support!</em></canvas><br />
In last week&#8217;s tutorial we used the canvas control to make a character&#8217;s eyes follow the mouse. This week Nelly the elephant is back again. This time we will add some animations and use a texture atlas.  </p>
<h2>Texture atlas</h2>
<p>Combining all the graphics in one texture atlas gives a performance boost and makes things more managable. (A texture atlas is a similar idea to a sprite sheet, except the the images are better packed to used less space.) I used our <a href="http://www.codeproject.com/Articles/330742/Texture-Atlas-Maker">in-house tool</a> to create the atlas from the original artwork and this is the result:<br />
<a href="http://astronautz.com/wordpress/wp-content/uploads/2012/01/images0.png"><img onload="init()" src="http://astronautz.com/wordpress/wp-content/uploads/2012/01/images0-270x300.png" alt="" title="images0" width="270" height="300" class="aligncenter size-medium wp-image-775" /></a><br />
Each image is packed into one big image. The tool also creates a xml file which tells us where in the atlas each image is located:<br />
<pre><pre class="brush: xml; gutter: false; tab-size: 2;">
&nbsp;&nbsp;&lt;texture file=&quot;images0.tga&quot;&gt;
&nbsp;&nbsp;&nbsp;&nbsp;&lt;image name=&quot;base&quot; x=&quot;212&quot; y=&quot;0&quot; width=&quot;97&quot; height=&quot;150&quot; xOffset=&quot;39&quot; yOffset=&quot;1&quot;/&gt;
&nbsp;&nbsp;&nbsp;&nbsp;&lt;image name=&quot;blink02&quot; x=&quot;306&quot; y=&quot;150&quot; width=&quot;96&quot; height=&quot;149&quot; xOffset=&quot;39&quot; yOffset=&quot;1&quot;/&gt;
&nbsp;&nbsp; ....
&nbsp;&nbsp;&lt;/texture&gt;
</pre></pre><br />
Each the location and size of each image is stored as well as an &#8220;offset&#8221;. The offset is used to &#8220;pad out&#8221; each frame, without wasting any space. <a href="http://astronautz.com/wordpress/wp-content/uploads/2012/01/offset2.png"><img src="http://astronautz.com/wordpress/wp-content/uploads/2012/01/offset2.png" alt="" title="offset" width="260" height="155" class="aligncenter size-full wp-image-737" /></a><br />
The atlas xml file is parsed using XMLHttpRequest:<br />
<pre><pre class="brush: javascript; gutter: false; tab-size: 2;">
var client = new XMLHttpRequest();
client.onreadystatechange = xmlHandler;
client.open(&quot;GET&quot;, &quot;http://astronautz.com/wordpress/atlas.xml&quot;);
client.send();
...
function xmlHandler() 
{
&nbsp;&nbsp;if (this.readyState == 4) 
&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;if (this.status == 200 || this.status == 0) 
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (this.responseXML != null)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var x = this.responseXML.getElementsByTagName(&quot;image&quot;); 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (x == null ) return;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for (var n = 0; n &lt; x.length; n++)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var atlasImage = new AtlasImage();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;atlasImage.load(x[n]);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;atlasMap[x[n].getAttribute(&quot;name&quot;)] = atlasImage;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;init2();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;alert(&quot;this.responseXML == null&quot;);
&nbsp;&nbsp;&nbsp;&nbsp;} 
&nbsp;&nbsp;&nbsp;&nbsp;else 
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;alert(&quot;this.status = &quot; + this.status);
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;}
}
</pre></pre><br />
We create an <em>AtlasImage</em> object for each image and store it in an map, with the image name as a key.<br />
<pre><pre class="brush: javascript; gutter: false; tab-size: 2;">
function AtlasImage()
{
&nbsp;&nbsp;this.m_x;
&nbsp;&nbsp;this.m_y;
&nbsp;&nbsp;this.m_width;
&nbsp;&nbsp;this.m_height;
&nbsp;&nbsp;this.m_xOffset;
&nbsp;&nbsp;this.m_yOffset;
&nbsp;&nbsp;this.load = function(elem)
&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;this.m_x = parseInt(elem.getAttribute(&quot;x&quot;)); 
&nbsp;&nbsp;&nbsp;&nbsp;this.m_y = parseInt(elem.getAttribute(&quot;y&quot;)); 
&nbsp;&nbsp;&nbsp;&nbsp;this.m_width = parseInt(elem.getAttribute(&quot;width&quot;));
&nbsp;&nbsp;&nbsp;&nbsp;this.m_height = parseInt(elem.getAttribute(&quot;height&quot;));
&nbsp;&nbsp;&nbsp;&nbsp;// offset is an optional parameter
&nbsp;&nbsp;&nbsp;&nbsp;if (elem.getAttribute(&quot;xOffset&quot;))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.m_xOffset = parseInt(elem.getAttribute(&quot;xOffset&quot;));
&nbsp;&nbsp;&nbsp;&nbsp;else
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.m_xOffset = 0;
&nbsp;&nbsp;&nbsp;&nbsp;if (elem.getAttribute(&quot;yOffset&quot;))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.m_yOffset = parseInt(elem.getAttribute(&quot;yOffset&quot;));
&nbsp;&nbsp;&nbsp;&nbsp;else
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.m_yOffset = 0;
&nbsp;&nbsp;}
&nbsp;&nbsp;this.render = function(x, y)
&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;context.drawImage(atlas, this.m_x, this.m_y,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.m_width, this.m_height, 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.m_xOffset+x, this.m_yOffset+y, 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.m_width, this.m_height);&nbsp;&nbsp;
&nbsp;&nbsp;}
};
</pre></pre></p>
<p>There are 4 animations: ear flap, trunk swing, blink and standing still. The <em>Animation </em> class controls the individual animations:<br />
<pre><pre class="brush: javascript; gutter: false; tab-size: 2;">
function Animation()
{
&nbsp;&nbsp;this.m_currFrame;
&nbsp;&nbsp;this.m_age;
&nbsp;&nbsp;this.m_listFrame = [];
&nbsp;&nbsp;this.m_moveEyes = true;

&nbsp;&nbsp;this.isFinished = function()
&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;return this.m_age &gt;= this.m_listFrame.length*1000/12;
&nbsp;&nbsp;}
&nbsp;&nbsp;this.start = function()
&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;this.m_age = 0;
&nbsp;&nbsp;&nbsp;&nbsp;this.m_currFrame = 0;
&nbsp;&nbsp;}
&nbsp;&nbsp;this.init = function(listIndex)
&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;this.start();
&nbsp;&nbsp;&nbsp;&nbsp;var image;
&nbsp;&nbsp;&nbsp;&nbsp;for (var n = 0; n &lt; listIndex.length; n++)
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;image = atlasMap[listIndex[n]];
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (image)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.m_listFrame.push(image);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else alert(&quot;missing image:&quot;+listIndex[n]);
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;}

&nbsp;&nbsp;this.update = function(timeElapsed)
&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;this.m_age += timeElapsed;
&nbsp;&nbsp;&nbsp;&nbsp;// 12 frames per second
&nbsp;&nbsp;&nbsp;&nbsp;this.m_currFrame = Math.floor(this.m_age/1000*12);
&nbsp;&nbsp;&nbsp;&nbsp;if (this.m_currFrame &gt;= this.m_listFrame.length)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.m_currFrame = this.m_listFrame.length-1;
&nbsp;&nbsp;}
&nbsp;&nbsp;this.render = function()
&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;this.m_listFrame[this.m_currFrame].render(0, 0);&nbsp;&nbsp;
&nbsp;&nbsp;}
};
</pre></pre><br />
You need to pass it a list of images that compose the animation sequence:<br />
<pre><pre class="brush: javascript; gutter: false; tab-size: 2;">
var earFlap = new Animation();
&nbsp;&nbsp;earFlap.init([&quot;base&quot;, &quot;earflap02&quot;, &quot;earflap04&quot;, &quot;earflap06&quot;, 
&nbsp;&nbsp;&nbsp;&nbsp;&quot;earflap08&quot;, &quot;earflap06&quot;, &quot;earflap04&quot;, &quot;earflap02&quot;, &quot;base&quot;]);
&nbsp;&nbsp;earFlap.m_moveEyes = false;
&nbsp;&nbsp;listAnim.push(earFlap);
</pre></pre><br />
Note: sometimes we use the same images several times in the same animation to save space.<br />
For some animation we don&#8217;t want the eyes to move, because the head moves in the animation. For these cases we set <em>m_moveEyes = false</em>.</p>
<p>The current animation is stored in a global variable <em>currAnim</em>. In the main game loop once an animation stops we randomly select a new one, by setting <em>currAnim</em> to a new animation:<br />
<pre><pre class="brush: javascript; gutter: false; tab-size: 2;">
function render() 
{&nbsp;&nbsp;
&nbsp;&nbsp;var timeElapsed = new Date().getTime() - lastRender;
&nbsp;&nbsp;lastRender = new Date().getTime();
&nbsp;&nbsp;if (currAnim.isFinished())
&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;var randNum = Math.floor(Math.random()*100);
&nbsp;&nbsp;&nbsp;&nbsp;if (randNum &lt; listAnim.length)
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;currAnim = listAnim[randNum];
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;else 
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// make it show stand still animation most of the time
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;currAnim = standStill;
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;currAnim.start();
&nbsp;&nbsp;}
&nbsp;&nbsp;context.clearRect(0, 0, canvasWidth, canvasHeight);
&nbsp;&nbsp;currAnim.update(timeElapsed);
&nbsp;&nbsp;currAnim.render();&nbsp;&nbsp;
&nbsp;&nbsp;if (currAnim.m_moveEyes == true)
&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;eyeRight.update();
&nbsp;&nbsp;&nbsp;&nbsp;eyeLeft.update();
&nbsp;&nbsp;&nbsp;&nbsp;eyeRight.render();
&nbsp;&nbsp;&nbsp;&nbsp;eyeLeft.render();
&nbsp;&nbsp;}
&nbsp;&nbsp;requestAnimFrame(render);&nbsp;&nbsp;
}&nbsp;&nbsp;
</pre></pre><br />
That&#8217;s all. Full source code can be found <a href="http://astronautz.com/wordpress/animateNelly.js">here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://astronautz.com/wordpress/html5-animation-using-texture-atlas/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>HTML5 Eyes that follow the mouse</title>
		<link>http://astronautz.com/wordpress/html5-eyes-that-follow-the-mouse/</link>
		<comments>http://astronautz.com/wordpress/html5-eyes-that-follow-the-mouse/#comments</comments>
		<pubDate>Sun, 08 Jan 2012 22:59:53 +0000</pubDate>
		<dc:creator>Ed Welch</dc:creator>
				<category><![CDATA[CodeProject]]></category>
		<category><![CDATA[web development]]></category>
		<category><![CDATA[canvas]]></category>
		<category><![CDATA[html5]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://astronautz.com/wordpress/?p=657</guid>
		<description><![CDATA[Your browser has no canvas control support! I made a cute flash movie of an elephant ages ago. Among other things the eyes of the elephant followed the cursor. Unfortunately subsequent flash security updates broke the functionality (if you want &#8230; <a href="http://astronautz.com/wordpress/html5-eyes-that-follow-the-mouse/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><script type="text/javascript" src="http://astronautz.com/wordpress/nelly.js"></script><br />
<canvas width="100" height="150" style="float: left; margin: 10px;" id="nelly"><em>Your browser has no canvas control support!</em></canvas><br />
I made a cute flash movie of an elephant ages ago. Among other things the eyes of the elephant followed the cursor. Unfortunately subsequent flash security updates broke the functionality (if you want mouse move events <em>outside </em>the flash control you need special permissions). So, I decided to convert it to HTML5. The result you can see to the left of this paragraph. (Note: if you see nothing, it&#8217;s because you have an old version of IE.).</p>
<h2>How it&#8217;s done</h2>
<p>I use an onload event handler somewhere in the html file which calls the <em>init()</em> function. E.g.:<br />
<pre><code>
&lt;body onload=&quot;init()&quot;&gt;
</code></pre><br />
In the <em>init()</em> function the images are loaded and the canvas resized and then the render loop is started via <em>requestAnimFrame</em>. All images are stored in the one png (this is known as an image atlas).<br />
<pre><pre class="brush: javascript; gutter: false; tab-size: 2;">
function init()
{
&nbsp;&nbsp;canvas = document.getElementById(&#039;nelly&#039;);
&nbsp;&nbsp;if (canvas.getContext)
&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;context = canvas.getContext(&#039;2d&#039;);
&nbsp;&nbsp;}
&nbsp;&nbsp;else
&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;return;
&nbsp;&nbsp;}
&nbsp;&nbsp;logElement = document.getElementById(&#039;log&#039;);
&nbsp;&nbsp;atlas = new Image();&nbsp;&nbsp;
&nbsp;&nbsp;atlas.src = &#039;http://astronautz.com/wordpress/nelly0.png&#039;;
&nbsp;&nbsp;atlas.onload = function()
&nbsp;&nbsp;{ 
&nbsp;&nbsp;&nbsp;&nbsp;window.addEventListener (&quot;mousemove&quot;, getCoords, true);
&nbsp;&nbsp;&nbsp;&nbsp;xCanvas = canvas.offsetLeft;
&nbsp;&nbsp;&nbsp;&nbsp;yCanvas = canvas.offsetTop;
&nbsp;&nbsp;&nbsp;&nbsp;var elem = canvas.offsetParent;
&nbsp;&nbsp;&nbsp;&nbsp;while (elem)
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;xCanvas += elem.offsetLeft;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;yCanvas += elem.offsetTop;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;elem = elem.offsetParent;
&nbsp;&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;&nbsp;backWidth = 97;
&nbsp;&nbsp;&nbsp;&nbsp;backHeight = 150;
&nbsp;&nbsp;&nbsp;&nbsp;canvas.width = backWidth;
&nbsp;&nbsp;&nbsp;&nbsp;canvas.height = backHeight;
&nbsp;&nbsp;&nbsp;&nbsp;eyeRight.setSize(4, 4);
&nbsp;&nbsp;&nbsp;&nbsp;eyeRight.setMin(44, 30);
&nbsp;&nbsp;&nbsp;&nbsp;eyeRight.setMax(54, 52);
&nbsp;&nbsp;&nbsp;&nbsp;eyeRight.setAtlas(97, 0);
&nbsp;&nbsp;&nbsp;&nbsp;eyeRight.init();
&nbsp;&nbsp;&nbsp;&nbsp;eyeLeft.setSize(4, 4);
&nbsp;&nbsp;&nbsp;&nbsp;eyeLeft.setMin(34, 30);
&nbsp;&nbsp;&nbsp;&nbsp;eyeLeft.setMax(39, 52);
&nbsp;&nbsp;&nbsp;&nbsp;eyeLeft.setAtlas(97, 0);
&nbsp;&nbsp;&nbsp;&nbsp;eyeLeft.init();
&nbsp;&nbsp;&nbsp;&nbsp;requestAnimFrame(render);
&nbsp;&nbsp;};&nbsp;&nbsp;
}
</pre></pre><br />
Note, that I create a event handler which stores the mouse coordinates in two global variables:<br />
<pre><pre class="brush: javascript; gutter: false; tab-size: 2;">
var xMouse = 0;
var yMouse = 0;
...
function getCoords(event) 
{
&nbsp;&nbsp;xMouse = event.clientX;
&nbsp;&nbsp;yMouse = event.clientY + window.pageYOffset;
};
...
window.addEventListener (&quot;mousemove&quot;, getCoords, true);

</pre></pre><br />
Each eye is controlled by an Eye object. It takes a min, max as parameters:<br />
<a href="http://astronautz.com/wordpress/wp-content/uploads/2012/01/minMax.png"><img onload="init()" src="http://astronautz.com/wordpress/wp-content/uploads/2012/01/minMax.png" alt="" title="minMax" width="307" height="279" class="aligncenter size-full wp-image-666" /></a><br />
It also needs the size of the eye image and it&#8217;s position within the image atlas before you initialise:<br />
<pre><pre class="brush: javascript; gutter: false; tab-size: 2;">
eyeRight.setSize(4, 4);
eyeRight.setMin(44, 30);
eyeRight.setMax(54, 52);
eyeRight.setAtlas(97, 0);
eyeRight.init();
</pre></pre><br />
The eye movement is calculated by getting the slope of the angle between the eyeball center and the current mouse position. Then you need to calculate the position taking into account the quadrant:<br />
<pre><pre class="brush: javascript; gutter: false; tab-size: 2;">
&nbsp;&nbsp;this.update = function()
&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;var xDiff = xMouse-(xCanvas+this.m_xOrig);
&nbsp;&nbsp;&nbsp;&nbsp;var yDiff = yMouse-(yCanvas+this.m_yOrig);
&nbsp;&nbsp;&nbsp;&nbsp;// first calculate x pos
&nbsp;&nbsp;&nbsp;&nbsp;if (yDiff == 0)
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (xDiff &gt; 0)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.m_x = this.m_xMax;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.m_x = this.m_xMin;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.m_y = this.m_yOrig;
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;else
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var slope = xDiff/yDiff;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (yDiff &gt; 0)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.m_x = slope*(this.m_xMax-this.m_xMin) + this.m_xMin;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.m_x = -slope*(this.m_xMax-this.m_xMin) + this.m_xMin;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;// then calculate y pos
&nbsp;&nbsp;&nbsp;&nbsp;if (xDiff == 0)
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (yDiff &gt; 0)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.m_y = this.m_yMax;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.m_y = this.m_yMin;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.m_x = this.m_xOrig;
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;else
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var slope = yDiff/xDiff;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (xDiff &gt; 0)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.m_y = slope*(this.m_yMax-this.m_yMin) + this.m_yMin;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.m_y = -slope*(this.m_yMax-this.m_yMin) + this.m_yMin;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;if (this.m_x &gt; this.m_xMax)
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.m_x = this.m_xMax;
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;else if (this.m_x &lt; this.m_xMin)
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.m_x = this.m_xMin;
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;if (this.m_y &gt; this.m_yMax)
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.m_y = this.m_yMax;
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;else if (this.m_y &lt; this.m_yMin)
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.m_y = this.m_yMin;
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;}
</pre></pre><br />
The full source code can be downloaded <a href="http://astronautz.com/wordpress/nelly.js" title="nelly.js">here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://astronautz.com/wordpress/html5-eyes-that-follow-the-mouse/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Creating realistic particle effect with HTML5 canvas</title>
		<link>http://astronautz.com/wordpress/creating-realistic-particle-effect-with-html5-canvas/</link>
		<comments>http://astronautz.com/wordpress/creating-realistic-particle-effect-with-html5-canvas/#comments</comments>
		<pubDate>Mon, 26 Dec 2011 19:26:03 +0000</pubDate>
		<dc:creator>Ed Welch</dc:creator>
				<category><![CDATA[web development]]></category>
		<category><![CDATA[html5]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[particle effect]]></category>

		<guid isPermaLink="false">http://astronautz.com/wordpress/?p=590</guid>
		<description><![CDATA[This is my first experiment with the HTML5 canvas &#8211; the so-called replacement for Flash. I tried to create a realistic smoke particle effect to go in the background of my war zone scene. As you can see above it&#8217;s &#8230; <a href="http://astronautz.com/wordpress/creating-realistic-particle-effect-with-html5-canvas/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><script type="text/javascript" src="http://astronautz.com/wordpress/peffect.js">
</script><br />
<img onload="init()" src="http://astronautz.com/wordpress/wp-content/uploads/2011/12/aftermath.jpg" alt="" title="aftermath" id="background" class="aligncenter size-full"/><br />
<canvas id="tutorial"></canvas></p>
<p>This is my first experiment with the HTML5 canvas &#8211; the so-called replacement for Flash. I tried to create a realistic smoke particle effect to go in the background of my war zone scene. As you can see above it&#8217;s worked out pretty well (unless you are using an old version of IE &#8211; which doesn&#8217;t support the canvas control).</p>
<h2>Tips</h2>
<ul>
<li>Copy from real life</li>
<p>To figure out how smoke behaves I first studied a video clip frame by frame. I found that the smoke is made up of individual puffs of smoke, which expand rapidly emerging from the fire and then slowly drift upwards expanding much slower and fading out. If you want realism I recommend observing the effect in real life, rather than creating it purely from your head, or copying some one else&#8217;s particle effect.</p>
<li>The further from camera, the slower</li>
<p>It&#8217;s important to take into account the distance the particle effect is from the camera. The further away, the <i>slower</i> the particles will move. For instance, the fireball of a huge spaceship exploding will almost appear to expand in slow motion. If you make the fireball expand too fast it will look like a tiny explosion to the viewer.
</ul>
<h2>Technical details</h2>
<p>I embed  a normal image in my html page as the background and then overlaid the canvas control on top of it, as follows:<br />
<pre><code>
&lt;html&gt;
...
&lt;body&gt;
&nbsp;&nbsp;&lt;img onload=&quot;init()&quot; src=&quot;aftermath.jpg&quot; id=&quot;background&quot;/&gt;
&nbsp;&nbsp;&lt;canvas id=&quot;tutorial&quot;&gt;&lt;/canvas&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre><br />
On loading the image the <em>init()</em> function is called which positions the canvas control to lie exactly on top of the background image.</p>
<p>To animate the canvas we use the same render loop as we do in games. This is what it looks like:<br />
<pre><pre class="brush: javascript; gutter: false; tab-size: 2;">
var lastRender = new Date().getTime();
var context;
var smokeRight = new ParticleEmitter();
function render()
 {
&nbsp;&nbsp;&nbsp;&nbsp; // time in milliseconds
&nbsp;&nbsp;&nbsp;&nbsp; var timeElapsed = new Date().getTime() - lastRender;
&nbsp;&nbsp;&nbsp;&nbsp; lastRender = new Date().getTime();
&nbsp;&nbsp;&nbsp;&nbsp; smokeRight.update(timeElapsed);
&nbsp;&nbsp;&nbsp;&nbsp; smokeRight.render(context);
&nbsp;&nbsp;&nbsp;&nbsp; requestAnimFrame(render);
 }
</pre></pre><br />
<em>requestAnimFrame </em>is an improved version of <em>setTimeout</em>. It calls our render function once every 16.66 ms ( i.e. 60 FPS). Every object typically has an <em>update</em> and <em>render</em> method. <em>update</em> is called with a <em>timeElapsed </em>parameter.  <em>timeElapsed</em> is the time in milliseconds since the last call. If you want everything to animate smoothly it is important that you make all movement calculations relative to this parameter.</p>
<p>There are two &#8220;classes&#8221; (really function objects, because javascript does not have classes, as such), <em>ParticleEmitter</em> and <em>Particle</em>.  <em>ParticleEmitter</em> creates an array of Particles and animates them:<br />
<pre><pre class="brush: javascript; gutter: false; tab-size: 2;">
function ParticleEmitter()
{
&nbsp;&nbsp;this.m_x;
&nbsp;&nbsp;this.m_y;
&nbsp;&nbsp;this.m_dieRate;
&nbsp;&nbsp;this.m_image;
&nbsp;&nbsp;this.m_speed = 0.02;
&nbsp;&nbsp;this.m_alpha = 1.0;

&nbsp;&nbsp;this.m_listParticle = [];

&nbsp;&nbsp;// ParticleEmitter().init function
&nbsp;&nbsp;// xScale = number between 0&nbsp;&nbsp;and 1. 0 = on left side 1 = on top
&nbsp;&nbsp;// yScale = number between 0&nbsp;&nbsp;and 1. 0 = on top 1 = on bottom
&nbsp;&nbsp;// particles = number of particles
&nbsp;&nbsp;// image = smoke graphic for each particle
&nbsp;&nbsp;this.init = function(xScale, yScale, particles, image)
&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;this.m_x = CANVAS_WIDTH*xScale;
&nbsp;&nbsp;&nbsp;&nbsp;this.m_y = CANVAS_HEIGHT*yScale;
&nbsp;&nbsp;&nbsp;&nbsp;this.m_image = image;
&nbsp;&nbsp;&nbsp;&nbsp;this.m_dieRate = 0.95;
&nbsp;&nbsp;&nbsp;&nbsp;// start with smoke already in place
&nbsp;&nbsp;&nbsp;&nbsp;for (var n = 0; n &lt; particles; n++)
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.m_listParticle.push(new Particle());
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.m_listParticle[n].init(this, n*50000*this.m_speed);
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;}

&nbsp;&nbsp;this.update = function(timeElapsed)
&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;for (var n = 0; n &lt; this.m_listParticle.length; n++)
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.m_listParticle[n].update(timeElapsed);
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;}

&nbsp;&nbsp;this.render = function(context)
&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;for (var n = 0; n &lt; this.m_listParticle.length; n++)
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.m_listParticle[n].render(context);
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;}
};
</pre></pre></p>
<p>Each Particle initialises itself around the location of the emitter. The update method cause the particle to expand, fade in, then fade out and move upwards depending on the age. Each particle has a random direction, velocity and lifespan. When <em>m_age &gt; m_timeDie</em> the particle is considered to be dead, at which case it is &#8220;reborn&#8221; at the location of the emitter again. This provides a continuous trail of smoke. (Well actually, I make it so that eventually the smoke stops according to the <em>m_dieRate </em>parameter).</p>
<p>The <em>init</em> function mentioned previously, loads the smoke puff graphic and the foreground character graphic and initialises the ParticleEmitters:<br />
<pre><pre class="brush: javascript; gutter: false; tab-size: 2;">
function init()
{
&nbsp;&nbsp;var canvas = document.getElementById(&#039;tutorial&#039;);
&nbsp;&nbsp;if (canvas.getContext)
&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;context = canvas.getContext(&#039;2d&#039;);
&nbsp;&nbsp;}
&nbsp;&nbsp;else
&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;return;
&nbsp;&nbsp;}
&nbsp;&nbsp;var imgBack = document.getElementById(&#039;background&#039;);
&nbsp;&nbsp;CANVAS_WIDTH = imgBack.width;
&nbsp;&nbsp;CANVAS_HEIGHT = imgBack.height;
&nbsp;&nbsp;canvas.width = imgBack.width;
&nbsp;&nbsp;canvas.height = imgBack.height;
&nbsp;&nbsp;var xImage = imgBack.offsetLeft;
&nbsp;&nbsp;var yImage = imgBack.offsetTop;
&nbsp;&nbsp;var elem = imgBack.offsetParent;
&nbsp;&nbsp;while (elem)
&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;xImage += elem.offsetLeft;
&nbsp;&nbsp;&nbsp;&nbsp;yImage += elem.offsetTop;
&nbsp;&nbsp;&nbsp;&nbsp;elem = elem.offsetParent;
&nbsp;&nbsp;}
&nbsp;&nbsp;canvas.style.position = &#039;absolute&#039;;
&nbsp;&nbsp;canvas.style.left = xImage + &quot;px&quot;;
&nbsp;&nbsp;canvas.style.top = (yImage) + &quot;px&quot;;
&nbsp;&nbsp;var imgSmoke = new Image();&nbsp;&nbsp;
&nbsp;&nbsp;imgSmoke.src = &#039;puffBlack.png&#039;;
&nbsp;&nbsp;imgSmoke.onload = function()
&nbsp;&nbsp;{ 
&nbsp;&nbsp;&nbsp;&nbsp;smokeRight.init(.9, .531, 20, imgSmoke);
&nbsp;&nbsp;&nbsp;&nbsp;smokeLeft.m_alpha = 0.3;
&nbsp;&nbsp;&nbsp;&nbsp;smokeLeft.init(.322, .453, 30, imgSmoke);
&nbsp;&nbsp;&nbsp;&nbsp;requestAnimFrame(render);
&nbsp;&nbsp;};&nbsp;&nbsp;
}
</pre></pre><br />
Only when the smoke image is finished loading is the first <em>requestAnimFrame</em> called, which kicks off the animation.</p>
<p>This is the graphic I used for the smoke particle:<br />
<a href="http://astronautz.com/wordpress/wp-content/uploads/2011/12/puffBlack.png"><img title="puffBlack" src="http://astronautz.com/wordpress/wp-content/uploads/2011/12/puffBlack.png" alt="" width="32" height="31" /></a></p>
<p>You may notice there is also a wind effect controlled by the global <em>windVelocity</em> variable. This changes slightly every frame, simulating puffs of wind.</p>
<h2>Optimisation</h2>
<p>Finally, there is a drawing optimisation. The <em>clearRect</em> method clears all, or part of the canvas. We are being smart and we only clear the smallest rectangle that is needed. We keep track of this with the global variables: <em>dirtyLeft, dirtyTop, dirtyRight, dirtyBottom</em>. This optimisation may not actually be necessary in our case &#8211; depends on what platforms you are targetting.  The canvas control is quite fast on PCs (even older browsers like Firefox 3.6), however mobile browsers will struggle. This example works on the iPhone (albeit with slightly jittery animation)</p>
<h2>Integration into WordPress</h2>
<p>To get the particle effect to work in WordPress insert the following into the post:<br />
<pre><code>
&lt;script type=&quot;text/javascript&quot; src=&quot;...peffect.js&quot;&gt;&lt;/script&gt;
&lt;img onload=&quot;init()&quot; id=&quot;background&quot; src=&quot;....background.jpg&quot; alt=&quot;&quot; title=&quot;aftermath&quot; 
class=&quot;aligncenter size-full&quot;/&gt;
&lt;canvas id=&quot;tutorial&quot;&gt;&lt;/canvas&gt;
</code></pre><br />
Then you need to upload the script via ftp and specify the full url for all file references (i.e <em>src=&#8221;http://mydomain.com/wordpress/peffect.js&#8221;</em> </p>
<h2>References</h2>
<p>I found the tutorial at <a href="https://developer.mozilla.org/en/Canvas_tutorial" target="_blank">Mozilla.org</a> to be very useful source on the canvas control. Also, <a href="http://www.html5rocks.com/en/tutorials/canvas/performance/" target="_blank">this article</a> has some great optimisation tips. </p>
<h2>Full listing</h2>
<p>Finally, here is a full listing of the code used:<br />
<pre><pre class="brush: javascript; gutter: false; tab-size: 2; ">
function ParticleEmitter()
{
&nbsp;&nbsp;this.m_x;
&nbsp;&nbsp;this.m_y;
&nbsp;&nbsp;this.m_dieRate;
&nbsp;&nbsp;this.m_image;
&nbsp;&nbsp;this.m_speed = 0.02;
&nbsp;&nbsp;this.m_alpha = 1.0;

&nbsp;&nbsp;this.m_listParticle = [];

&nbsp;&nbsp;// ParticleEmitter().init function
&nbsp;&nbsp;// xScale = number between 0&nbsp;&nbsp;and 1. 0 = on left side 1 = on top
&nbsp;&nbsp;// yScale = number between 0&nbsp;&nbsp;and 1. 0 = on top 1 = on bottom
&nbsp;&nbsp;// particles = number of particles
&nbsp;&nbsp;// image = smoke graphic for each particle
&nbsp;&nbsp;this.init = function(xScale, yScale, particles, image)
&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;// the effect is positioned relative to the width and height of the canvas
&nbsp;&nbsp;&nbsp;&nbsp;this.m_x = CANVAS_WIDTH*xScale;
&nbsp;&nbsp;&nbsp;&nbsp;this.m_y = CANVAS_HEIGHT*yScale;
&nbsp;&nbsp;&nbsp;&nbsp;this.m_image = image;
&nbsp;&nbsp;&nbsp;&nbsp;this.m_dieRate = 0.95;
&nbsp;&nbsp;&nbsp;&nbsp;// start with smoke already in place
&nbsp;&nbsp;&nbsp;&nbsp;for (var n = 0; n &lt; particles; n++)
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.m_listParticle.push(new Particle());
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.m_listParticle[n].init(this, n*50000*this.m_speed);
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;}

&nbsp;&nbsp;this.update = function(timeElapsed)
&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;for (var n = 0; n &lt; this.m_listParticle.length; n++)
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.m_listParticle[n].update(timeElapsed);
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;}

&nbsp;&nbsp;this.render = function(context)
&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;for (var n = 0; n &lt; this.m_listParticle.length; n++)
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.m_listParticle[n].render(context);
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;}
};

function Particle()
{
&nbsp;&nbsp;this.m_x;
&nbsp;&nbsp;this.m_y;
&nbsp;&nbsp;this.m_age;
&nbsp;&nbsp;this.m_xVector;
&nbsp;&nbsp;this.m_yVector;
&nbsp;&nbsp;this.m_scale;
&nbsp;&nbsp;this.m_alpha;
&nbsp;&nbsp;this.m_canRegen;
&nbsp;&nbsp;this.m_timeDie;
&nbsp;&nbsp;this.m_emitter;
&nbsp;&nbsp;
&nbsp;&nbsp;this.init = function(emitter, age)
&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;this.m_age = age;
&nbsp;&nbsp;&nbsp;&nbsp;this.m_emitter = emitter;
&nbsp;&nbsp;&nbsp;&nbsp;this.m_canRegen = true;
&nbsp;&nbsp;&nbsp;&nbsp;this.startRand();
&nbsp;&nbsp;}

&nbsp;&nbsp;this.isAlive = function () 
&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;return this.m_age &lt; this.m_timeDie;
&nbsp;&nbsp;}

&nbsp;&nbsp;this.startRand = function()
&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;// smoke rises and spreads
&nbsp;&nbsp;&nbsp;&nbsp;this.m_xVector = Math.random()*0.5 - 0.25;
&nbsp;&nbsp;&nbsp;&nbsp;this.m_yVector = -1.5 - Math.random();
&nbsp;&nbsp;&nbsp;&nbsp;this.m_timeDie = 20000 + Math.floor(Math.random()*12000);

&nbsp;&nbsp;&nbsp;&nbsp;var invDist = 1.0/Math.sqrt(this.m_xVector*this.m_xVector 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;+ this.m_yVector*this.m_yVector);
&nbsp;&nbsp;&nbsp;&nbsp;// normalise speed
&nbsp;&nbsp;&nbsp;&nbsp;this.m_xVector = this.m_xVector*invDist*this.m_emitter.m_speed;
&nbsp;&nbsp;&nbsp;&nbsp;this.m_yVector = this.m_yVector*invDist*this.m_emitter.m_speed;
&nbsp;&nbsp;&nbsp;&nbsp;// starting position within a 20 pixel area 
&nbsp;&nbsp;&nbsp;&nbsp;this.m_x = (this.m_emitter.m_x + Math.floor(Math.random()*20)-10);
&nbsp;&nbsp;&nbsp;&nbsp;this.m_y = (this.m_emitter.m_y + Math.floor(Math.random()*20)-10);
&nbsp;&nbsp;&nbsp;&nbsp;// the initial age may be &gt; 0. This is so there is already a smoke trail in 
&nbsp;&nbsp;&nbsp;&nbsp;// place at the start
&nbsp;&nbsp;&nbsp;&nbsp;this.m_x += (this.m_xVector+windVelocity)*this.m_age;
&nbsp;&nbsp;&nbsp;&nbsp;this.m_y += this.m_yVector*this.m_age;
&nbsp;&nbsp;&nbsp;&nbsp;this.m_scale = 0.01;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;this.m_alpha = 0.0;
&nbsp;&nbsp;}

&nbsp;&nbsp;this.update = function(timeElapsed)
&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;this.m_age += timeElapsed;
&nbsp;&nbsp;&nbsp;&nbsp;if (!this.isAlive()) 
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// smoke eventually dies
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (Math.random() &gt; this.m_emitter.m_dieRate)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.m_canRegen = false;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (!this.m_canRegen)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// regenerate
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.m_age = 0;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.startRand();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return;
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;// At start the particle fades in and expands rapidly (like in real life)
&nbsp;&nbsp;&nbsp;&nbsp;var fadeIn = this.m_timeDie * 0.05;
&nbsp;&nbsp;&nbsp;&nbsp;var startScale;
&nbsp;&nbsp;&nbsp;&nbsp;var maxStartScale = 0.3;
&nbsp;&nbsp;&nbsp;&nbsp;if (this.m_age &lt; fadeIn)
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.m_alpha = this.m_age/fadeIn;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;startScale = this.m_alpha*maxStartScale; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// y increases quicker because particle is expanding quicker
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.m_y += this.m_yVector*2.0*timeElapsed;
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;else
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.m_alpha = 1.0 - (this.m_age-fadeIn)/(this.m_timeDie-fadeIn);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;startScale = maxStartScale;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.m_y += this.m_yVector*timeElapsed;
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;// the x direction is influenced by wind velocity
&nbsp;&nbsp;&nbsp;&nbsp;this.m_x += (this.m_xVector+windVelocity)*timeElapsed;
&nbsp;&nbsp;&nbsp;&nbsp;this.m_alpha *= this.m_emitter.m_alpha;
&nbsp;&nbsp;&nbsp;&nbsp;this.m_scale = 0.001 + startScale + this.m_age/4000.0;
&nbsp;&nbsp;}

&nbsp;&nbsp;this.render = function(ctx)
&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;if (!this.isAlive()) return;
&nbsp;&nbsp;&nbsp;&nbsp;ctx.globalAlpha = this.m_alpha;
&nbsp;&nbsp;&nbsp;&nbsp;var height = this.m_emitter.m_image.height*this.m_scale;
&nbsp;&nbsp;&nbsp;&nbsp;var width = this.m_emitter.m_image.width*this.m_scale;
&nbsp;&nbsp;&nbsp;&nbsp;// round it to a integer to prevent subpixel positioning
&nbsp;&nbsp;&nbsp;&nbsp;var x = Math.round(this.m_x-width/2);
&nbsp;&nbsp;&nbsp;&nbsp;var y = Math.round(this.m_y+height/2);
&nbsp;&nbsp;&nbsp;&nbsp;ctx.drawImage(this.m_emitter.m_image, x, y, width, height);&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;if (x &lt; dirtyLeft)
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dirtyLeft = x;
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;if (x+width &gt; dirtyRight)
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dirtyRight = x+width;
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;if (y &lt; dirtyTop)
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dirtyTop = y;
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;if (y+height &gt; dirtyBottom)
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dirtyBottom = y+height;
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;}
};

var lastRender = new Date().getTime();
var context;
var smokeRight = new ParticleEmitter();
var smokeLeft = new ParticleEmitter();
var CANVAS_WIDTH = 960;
var CANVAS_HEIGHT = 640;
// only redraw minimimum rectangle
var dirtyLeft = 0;
var dirtyTop = 0;
var dirtyRight = CANVAS_WIDTH;
var dirtyBottom = CANVAS_HEIGHT;
var windVelocity = 0.01;
var count = 0;

function init()
{
&nbsp;&nbsp;var canvas = document.getElementById(&#039;tutorial&#039;);
&nbsp;&nbsp;if (canvas.getContext)
&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;context = canvas.getContext(&#039;2d&#039;);
&nbsp;&nbsp;}
&nbsp;&nbsp;else
&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;return;
&nbsp;&nbsp;}
&nbsp;&nbsp;var imgBack = document.getElementById(&#039;background&#039;);
&nbsp;&nbsp;// make canvas same size as background image
&nbsp;&nbsp;CANVAS_WIDTH = imgBack.width;
&nbsp;&nbsp;CANVAS_HEIGHT = imgBack.height;
&nbsp;&nbsp;canvas.width = imgBack.width;
&nbsp;&nbsp;canvas.height = imgBack.height;
&nbsp;&nbsp;// get absolute position of background image
&nbsp;&nbsp;var xImage = imgBack.offsetLeft;
&nbsp;&nbsp;var yImage = imgBack.offsetTop;
&nbsp;&nbsp;var elem = imgBack.offsetParent;
&nbsp;&nbsp;while (elem)
&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;xImage += elem.offsetLeft;
&nbsp;&nbsp;&nbsp;&nbsp;yImage += elem.offsetTop;
&nbsp;&nbsp;&nbsp;&nbsp;elem = elem.offsetParent;
&nbsp;&nbsp;}
&nbsp;&nbsp;// position canvas on top of background
&nbsp;&nbsp;canvas.style.position = &#039;absolute&#039;;
&nbsp;&nbsp;canvas.style.left = xImage + &quot;px&quot;;
&nbsp;&nbsp;canvas.style.top = yImage + &quot;px&quot;;
&nbsp;&nbsp;var imgSmoke = new Image();&nbsp;&nbsp;
&nbsp;&nbsp;imgSmoke.src = &#039;puffBlack.png&#039;;
&nbsp;&nbsp;imgSmoke.onload = function()
&nbsp;&nbsp;{ 
&nbsp;&nbsp;&nbsp;&nbsp;smokeRight.init(.9, .531, 20, imgSmoke);
&nbsp;&nbsp;&nbsp;&nbsp;smokeLeft.m_alpha = 0.3;
&nbsp;&nbsp;&nbsp;&nbsp;smokeLeft.init(.322, .453, 30, imgSmoke);
&nbsp;&nbsp;&nbsp;&nbsp;requestAnimFrame(render);
&nbsp;&nbsp;};&nbsp;&nbsp;
}

// shim layer with setTimeout fallback
&nbsp;&nbsp;&nbsp;&nbsp;window.requestAnimFrame = (function(){
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;&nbsp;window.requestAnimationFrame&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; || 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;window.webkitRequestAnimationFrame || 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;window.mozRequestAnimationFrame&nbsp;&nbsp;&nbsp;&nbsp;|| 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;window.oRequestAnimationFrame&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|| 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;window.msRequestAnimationFrame&nbsp;&nbsp;&nbsp;&nbsp; || 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;function( callback ){
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;window.setTimeout(callback, 17);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;};
&nbsp;&nbsp;&nbsp;&nbsp;})();

&nbsp;&nbsp;
function render() 
{&nbsp;&nbsp;
&nbsp;&nbsp;// time in milliseconds
&nbsp;&nbsp;var timeElapsed = new Date().getTime() - lastRender;
&nbsp;&nbsp;lastRender = new Date().getTime();
&nbsp;&nbsp;context.clearRect(dirtyLeft, dirtyTop, dirtyRight-dirtyLeft, dirtyBottom-dirtyTop);
&nbsp;&nbsp;dirtyLeft = 1000;
&nbsp;&nbsp;dirtyTop = 1000;
&nbsp;&nbsp;dirtyRight = 0;
&nbsp;&nbsp;dirtyBottom = 0;
&nbsp;&nbsp;smokeRight.update(timeElapsed);
&nbsp;&nbsp;smokeRight.render(context);
&nbsp;&nbsp;smokeLeft.update(timeElapsed);
&nbsp;&nbsp;smokeLeft.render(context);
&nbsp;&nbsp;windVelocity += (Math.random()-0.5)*0.002;
&nbsp;&nbsp;if (windVelocity &gt; 0.015)
&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;windVelocity = 0.015;
&nbsp;&nbsp;}
&nbsp;&nbsp;if (windVelocity &lt; 0.0)
&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;windVelocity = 0.0;
&nbsp;&nbsp;}
&nbsp;&nbsp;requestAnimFrame(render);&nbsp;&nbsp;
}&nbsp;&nbsp;
</pre></pre></p>
]]></content:encoded>
			<wfw:commentRss>http://astronautz.com/wordpress/creating-realistic-particle-effect-with-html5-canvas/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Protected: Warlord game design: a brief skim through</title>
		<link>http://astronautz.com/wordpress/warlord-game-design/</link>
		<comments>http://astronautz.com/wordpress/warlord-game-design/#comments</comments>
		<pubDate>Wed, 10 Aug 2011 23:28:06 +0000</pubDate>
		<dc:creator>Ed Welch</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://astronautz.com/wordpress/?p=508</guid>
		<description><![CDATA[There is no excerpt because this is a protected post.]]></description>
			<content:encoded><![CDATA[<form action="http://astronautz.com/wordpress/wp-pass.php" method="post">
<p>This post is password protected. To view it please enter your password below:</p>
<p><label for="pwbox-508">Password:<br />
<input name="post_password" id="pwbox-508" type="password" size="20" /></label><br />
<input type="submit" name="Submit" value="Submit" /></p></form>
]]></content:encoded>
			<wfw:commentRss>http://astronautz.com/wordpress/warlord-game-design/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>XML: Killing the Bloat</title>
		<link>http://astronautz.com/wordpress/xml-killing-the-bloat/</link>
		<comments>http://astronautz.com/wordpress/xml-killing-the-bloat/#comments</comments>
		<pubDate>Sun, 23 Jan 2011 19:52:45 +0000</pubDate>
		<dc:creator>Ed Welch</dc:creator>
				<category><![CDATA[CodeProject]]></category>
		<category><![CDATA[XML]]></category>

		<guid isPermaLink="false">http://astronautz.com/wordpress/?p=27</guid>
		<description><![CDATA[Many people criticise XML for being unnecessarily verbose, which is true. What they may not realise is that the bloat can be easily be slimmed down by storing the data in attributes instead of elements. Example of bloated XML: The &#8230; <a href="http://astronautz.com/wordpress/xml-killing-the-bloat/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Many people criticise XML for being unnecessarily verbose, which is true. What they may not realise is that the bloat can be easily be slimmed down by storing the data in attributes instead of elements.</p>
<p>Example of bloated XML:</p>
<blockquote><p><a href="http://astronautz.com/wordpress/wp-content/uploads/2011/01/bloatedXML.png"><img class="aligncenter size-full wp-image-28" title="bloated XML" src="http://astronautz.com/wordpress/wp-content/uploads/2011/01/bloatedXML.png" alt="" width="649" height="181" /></a></p></blockquote>
<p>The same info can be stored in a much more compact fashion:</p>
<p><img class="aligncenter size-full wp-image-30" title="slim XML" src="http://astronautz.com/wordpress/wp-content/uploads/2011/01/slimXML1.png" alt="slim XML example" width="813" height="127" />The slimmed down version has many advantages:</p>
<ul>
<li>Easier to read</li>
<li>Faster to load</li>
<li>Uses up less disk space and bandwidth</li>
</ul>
<p>Of coarse, you could achieve the same results by just using JSON, but then you lose out on the XML buzzword <img src='http://astronautz.com/wordpress/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://astronautz.com/wordpress/xml-killing-the-bloat/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Tiling system used in Armageddon Wars</title>
		<link>http://astronautz.com/wordpress/tiling-system-used-in-armageddon-wars/</link>
		<comments>http://astronautz.com/wordpress/tiling-system-used-in-armageddon-wars/#comments</comments>
		<pubDate>Sun, 23 Jan 2011 17:22:36 +0000</pubDate>
		<dc:creator>Ed Welch</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[2d games]]></category>
		<category><![CDATA[art]]></category>
		<category><![CDATA[graphics]]></category>

		<guid isPermaLink="false">http://astronautz.com/wordpress/?p=8</guid>
		<description><![CDATA[Traditional Grid system The traditional tiled game uses tiles that are opaque and the same size and shape &#8211; usually square or hexagonal &#8211; and located side by side in a &#8220;grid&#8221;. This system has many disadvantages.  The artist has &#8230; <a href="http://astronautz.com/wordpress/tiling-system-used-in-armageddon-wars/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><strong>Traditional Grid system</strong></p>
<p>The traditional tiled game uses tiles that are opaque and the same size   and shape &#8211; usually square or hexagonal &#8211; and located side by side in a   &#8220;grid&#8221;.</p>
<p><a href="http://astronautz.com/wordpress/wp-content/uploads/2011/01/traditionalTiles.png"><img class="aligncenter size-full wp-image-12" title="Traditional tiles" src="http://astronautz.com/wordpress/wp-content/uploads/2011/01/traditionalTiles.png" alt="" width="397" height="215" /></a>This system has many disadvantages.  The artist has   to create a lot more tiles to provide  variety in the landscape. Also,  extra tiles need to be created to provide the borders between one type  of terrain and an other &#8211; for essentially what is the same graphic. The end result will still look like it&#8217;s created out of a grid of tiles.</p>
<p><strong>The &#8220;Big Pile of Tiles&#8221; system</strong></p>
<p>So, how to we create a better tiling  system? The answer is quite  obvious &#8211; just remove all the restrictions.  Get rid of the grid idea  completely, so you just have a &#8220;big pile of  tiles&#8221;. Tiles are alpha  transparent and can be layered on top of each other many times. Each  tile can be located anywhere in the scene and it can have any  orientation, scaling, or transparency. Now days  most devices have a decent graphics processor and can handle this easily.</p>
<p><strong>Step-by-step example</strong></p>
<p>This is an example of  a landscape created using this system:<a href="http://astronautz.com/wordpress/wp-content/uploads/2010/10/scene.png"><br />
</a><a href="http://astronautz.com/wordpress/wp-content/uploads/2010/10/scene.png"> </a><a href="http://astronautz.com/wordpress/wp-content/uploads/2011/01/level4.png"><img class="aligncenter size-full wp-image-13" title="level4" src="http://astronautz.com/wordpress/wp-content/uploads/2011/01/level4.png" alt="example of landscape" width="374" height="348" /></a>The above scene was created using these tiles:</p>
<p><a href="http://astronautz.com/wordpress/wp-content/uploads/2011/01/bottomtiles.png"><img class="aligncenter size-full wp-image-14" title="bottomtiles" src="http://astronautz.com/wordpress/wp-content/uploads/2011/01/bottomtiles.png" alt="" width="547" height="304" /></a>First we started with the opaque square base tile and lay this tile down side-by-side. This provides a fine level of detail underneath the other tiles.</p>
<p><a href="http://astronautz.com/wordpress/wp-content/uploads/2011/01/base.png"><img class="aligncenter size-full wp-image-15" title="base" src="http://astronautz.com/wordpress/wp-content/uploads/2011/01/base.png" alt="" width="336" height="259" /></a></p>
<p>Then we add the mottled tile to add larger levels of detail. The same tile is added several times with different scaling and rotation.</p>
<p><a href="http://astronautz.com/wordpress/wp-content/uploads/2011/01/level0.png"><img class="aligncenter size-full wp-image-16" title="level0" src="http://astronautz.com/wordpress/wp-content/uploads/2011/01/level0.png" alt="" width="371" height="270" /></a></p>
<p>Next we add the black and white tiles to create dark and light areas:</p>
<p><a href="http://astronautz.com/wordpress/wp-content/uploads/2011/01/level1.png"><img class="aligncenter size-full wp-image-17" title="level1" src="http://astronautz.com/wordpress/wp-content/uploads/2011/01/level1.png" alt="" width="356" height="332" /></a>Then, we add the road tiles:</p>
<p><a href="http://astronautz.com/wordpress/wp-content/uploads/2011/01/level2.png"><img class="aligncenter size-full wp-image-18" title="level2" src="http://astronautz.com/wordpress/wp-content/uploads/2011/01/level2.png" alt="" width="353" height="325" /></a><br />
Finally, some gray tiles at the top and cracks:</p>
<p><a href="http://astronautz.com/wordpress/wp-content/uploads/2011/01/level41.png"><img class="aligncenter size-full wp-image-19" title="level4" src="http://astronautz.com/wordpress/wp-content/uploads/2011/01/level41.png" alt="" width="374" height="348" /></a>As you can see, with just a small selection of tiles we can create a  wide variety of landscape and the result does not look like it&#8217;s built  out of tiles.<br />
The tile editor creates these tiles in a text file. This is what the above scene tiles looks like:</p>
<p><pre><code>tile name=plainTile type=base
tile name=stainWhite1 x=-32 y=424 zorder=1 alpha=30 scale=5.3
tile name=stainWhite1 x=107 y=346 zorder=1 alpha=45 scale=5.3 rotation=330
tile name=stainBlack4 x=134 y=259 zorder=1 alpha=65
tile name=stainBlack4 x=-40 y=217 zorder=1 alpha=85 scale=1.8
tile name=plaza3 x=207 y=211 zorder=1 alpha=85 scale=1.55 rotation=68
tile name=plaza3 x=37 y=198 zorder=1 scale=1.7 rotation=346
tile name=stainRect x=-63 y=369 zorder=2 alpha=50 scale=1.05 rotation=264
tile name=stainRect x=582 y=237 zorder=2 alpha=60 scale=2 rotation=280
tile name=stainRect x=966 y=17 zorder=2 alpha=70 scale=1.45 rotation=359
tile name=stainRegular3 x=306 y=529 zorder=2 alpha=80 scale=1.9 rotation=267
tile name=roadBroken1 x=55 y=373 zorder=4 alpha=50 rotation=263
tile name=roadNarrow3 x=361 y=401 zorder=4 alpha=55 rotation=350
tile name=roadNarrow3 x=327 y=722 zorder=4 alpha=60 scale=1.15 rotation=248</code></pre></p>
<p>This is what the final scene looks like with buildings added in:</p>
<p><a href="http://astronautz.com/wordpress/wp-content/uploads/2011/01/level5.png"><img class="aligncenter size-full wp-image-20" title="level5" src="http://astronautz.com/wordpress/wp-content/uploads/2011/01/level5.png" alt="" width="363" height="338" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://astronautz.com/wordpress/tiling-system-used-in-armageddon-wars/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Removing randomness for testing</title>
		<link>http://astronautz.com/wordpress/removing_randomness_for_testing/</link>
		<comments>http://astronautz.com/wordpress/removing_randomness_for_testing/#comments</comments>
		<pubDate>Sat, 22 Jan 2011 01:41:12 +0000</pubDate>
		<dc:creator>Ed Welch</dc:creator>
				<category><![CDATA[Testing]]></category>

		<guid isPermaLink="false">http:/?p=1</guid>
		<description><![CDATA[Normally, games have some sort of randomness. This makes it difficult to test because each time you play the game a different set of events occur. I had this idea to have a switchable random number class. Normally, the class &#8230; <a href="http://astronautz.com/wordpress/removing_randomness_for_testing/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Normally, games have some sort of randomness. This makes it difficult to test because each time you play the game a different set of events occur.</p>
<p>I had this idea to have a switchable random number class. Normally, the class returns a random number, but when the test flag is set, it returns numbers in  a pre determined sequence.<br />
Here&#8217;s the code:<br />
<pre><pre class="brush: cpp; gutter: false; tab-size: 4;">class RandNumber
{
public:
&nbsp;&nbsp;RandNumber();
&nbsp;&nbsp;~RandNumber();
&nbsp;&nbsp;void LoadSeq();
&nbsp;&nbsp;void GenSeq();
&nbsp;&nbsp;int GetInt(int max)
&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;int randNum;
&nbsp;&nbsp;&nbsp;&nbsp;if (m_listSeq.empty())
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;randNum = rand();
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;else
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;randNum = m_listSeq[m_currSeqIX];
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_currSeqIX++;
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;randNum = int((float)randNum*max*m_invRandMax);
&nbsp;&nbsp;&nbsp;&nbsp;return randNum;
&nbsp;&nbsp;}
&nbsp;&nbsp;float GetFloat(float max)
&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;int randNum;
&nbsp;&nbsp;&nbsp;&nbsp;if (m_listSeq.empty())
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;randNum = rand();
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;else
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;randNum = m_listSeq[m_currSeqIX];
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_currSeqIX++;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (m_currSeqIX == (int)m_listSeq.size())
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_currSeqIX = 0;
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;return (float)randNum*max*m_invRandMax;
&nbsp;&nbsp;}
private:
&nbsp;&nbsp;vector m_listSeq;
&nbsp;&nbsp;int m_currSeqIX;
&nbsp;&nbsp;float m_invRandMax;
};</pre></pre><br />
You need to call GenSeq() initially to create the file with the sequence of numbers.<br />
<pre><pre class="brush: cpp; gutter: false; tab-size: 4;">#include &quot;RandNumber.h&quot;

RandNumber::RandNumber()
{
&nbsp;&nbsp;m_invRandMax = 1.0f/(float)RAND_MAX;
}

RandNumber::~RandNumber()
{
}

const char* szSeqFilename = &quot;randSeq.txt&quot;;

void RandNumber::LoadSeq()
{
&nbsp;&nbsp;FILE* pFile;
&nbsp;&nbsp;pFile = fopen(szSeqFilename, &quot;rb&quot;);
&nbsp;&nbsp;if (pFile == NULL)
&nbsp;&nbsp;&nbsp;&nbsp;throw RacException(&quot;cannot open &quot;, szSeqFilename);
&nbsp;&nbsp;m_currSeqIX = 0;
&nbsp;&nbsp;char* pBuffer;

&nbsp;&nbsp;fseek(pFile, 0, 2 /* SEEK_END */);
&nbsp;&nbsp;int fileSize = (int)ftell(pFile);
&nbsp;&nbsp;if (fileSize == 0) return;
&nbsp;&nbsp;fseek(pFile, 0, 0 /* SEEK_SET */);
&nbsp;&nbsp;pBuffer = new char[fileSize];
&nbsp;&nbsp;int bytesRead = (int)fread(pBuffer, fileSize, 1, pFile);&nbsp;&nbsp;// read length and type
&nbsp;&nbsp;if (bytesRead != 1)
&nbsp;&nbsp;&nbsp;&nbsp;throw RacException(&quot;cannot read &quot;, szSeqFilename);
&nbsp;&nbsp;fclose(pFile);

&nbsp;&nbsp;char* szToken;
&nbsp;&nbsp;szToken = strtok(pBuffer,&quot;,&quot;);
&nbsp;&nbsp;while(szToken != NULL)
&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;m_listSeq.push_back(atoi(szToken));
&nbsp;&nbsp;&nbsp;&nbsp;szToken = strtok(NULL, &quot;,&quot;);
&nbsp;&nbsp;}
&nbsp;&nbsp;delete [] pBuffer;
}

void RandNumber::GenSeq()
{
&nbsp;&nbsp;string file = g_resManager.GetDirResources()+szSeqFilename;
&nbsp;&nbsp;FILE* pFile = fopen(file.c_str(), &quot;wt&quot;);
&nbsp;&nbsp;if (pFile == NULL)
&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;assert(false);
&nbsp;&nbsp;&nbsp;&nbsp;return;
&nbsp;&nbsp;}
&nbsp;&nbsp;ostringstream os;
&nbsp;&nbsp;for (int n = 0; n &amp;lt; 10000; n++)
&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;os &amp;lt;&amp;lt; rand() &amp;lt;&amp;lt; &quot;,&quot;;
&nbsp;&nbsp;}
&nbsp;&nbsp;fwrite(os.str().c_str(), os.str().length(), 1, pFile);
&nbsp;&nbsp;fclose(pFile);
}</pre></pre></p>
]]></content:encoded>
			<wfw:commentRss>http://astronautz.com/wordpress/removing_randomness_for_testing/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Optimizing meshes for the iPhone</title>
		<link>http://astronautz.com/wordpress/optimizing-meshes-for-the-iphone/</link>
		<comments>http://astronautz.com/wordpress/optimizing-meshes-for-the-iphone/#comments</comments>
		<pubDate>Sat, 13 Nov 2010 18:25:58 +0000</pubDate>
		<dc:creator>Ed Welch</dc:creator>
				<category><![CDATA[Graphic engine design]]></category>
		<category><![CDATA[graphics]]></category>
		<category><![CDATA[iPhone development]]></category>
		<category><![CDATA[OpenGL]]></category>
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://astronautz.wordpress.com/?p=412</guid>
		<description><![CDATA[The PowerVR guide says if you order triangle indices as if they were triangle strips you will get a speed boost, because the PowerVR chip implementation uses  triangle strips internally. The PowerVR SDK has an example to shows this, using &#8230; <a href="http://astronautz.com/wordpress/optimizing-meshes-for-the-iphone/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>The PowerVR guide says if you order triangle indices as if they were triangle strips you will get a speed boost, because the PowerVR chip implementation uses  triangle strips internally. The PowerVR SDK has an example to shows this, using a model of a sphere. I assumed that the example was an extreme case and you wouldn&#8217;t see such a big improvement for real models. However, I was pleasantly surprised to see that it actually did give a big improvement in a real world example &#8211; cutting down render time from 38ms to 35.5ms in a scene with 18 skinned meshes.</p>
<p>I used tootle to re-order the indices:<br />
<pre><pre>int result = TootleOptimizeVCache(pIndices,
      numTriIndices/3, m_listVertexArray[0]-&amp;gt;GetNumVertices(),
      TOOTLE_DEFAULT_VCACHE_SIZE, pIndices, NULL, TOOTLE_VCACHE_LSTRIPS);
if (result != TOOTLE_OK)
    cout &amp;lt;&amp;lt; &quot;could not optimise!&quot; &amp;lt;&amp;lt; endl;</pre></pre><br />
It&#8217;s important to use TOOTLE_VCACHE_LSTRIPS, because the default ordering is designed for PC GPUs and won&#8217;t work well on the iPhone.<br />
Also, you have to reorder the vertex data to match the order in the triangle index array. Tootle can be found <a href="http://developer.amd.com/archive/gpu/tootle/Pages/default.aspx">here</a>.<br />
Unfortunately, Tootle crashes for certain meshes. If there was source code, I probably could have fixed that &#8211; but there isn&#8217;t <img src='http://astronautz.com/wordpress/wp-includes/images/smilies/icon_sad.gif' alt=':(' class='wp-smiley' /> .</p>
]]></content:encoded>
			<wfw:commentRss>http://astronautz.com/wordpress/optimizing-meshes-for-the-iphone/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Minified using disk: basic
Page Caching using disk: enhanced
Database Caching using disk: basic
Object Caching 513/730 objects using disk: basic

Served from: astronautz.com @ 2012-05-20 11:59:27 -->
