<?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>SONAR</title>
	<atom:link href="http://sonargame.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://sonargame.com</link>
	<description></description>
	<lastBuildDate>Wed, 30 Nov 2011 20:30:47 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>New Game Videos</title>
		<link>http://sonargame.com/2011/11/30/new-game-videos/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=new-game-videos</link>
		<comments>http://sonargame.com/2011/11/30/new-game-videos/#comments</comments>
		<pubDate>Wed, 30 Nov 2011 20:30:47 +0000</pubDate>
		<dc:creator>Sean</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://sonargame.com/?p=510</guid>
		<description><![CDATA[The videos from New Game are now up. The videos page can be found New Game Youtube Channel. Naturally, Jason and Sean's video on SONAR is among them. Enjoy!]]></description>
			<content:encoded><![CDATA[<p>The videos from <a href="http://newgameconf.com">New Game</a> are now up.  The videos page can be found <a href="http://www.youtube.com/NewGameConference">New Game Youtube Channel</a>.  Naturally, <a href="http://www.youtube.com/NewGameConference#p/u/6/ABozd7kh8qE">Jason and Sean's video on SONAR</a> is among them.  Enjoy!</p>
]]></content:encoded>
			<wfw:commentRss>http://sonargame.com/2011/11/30/new-game-videos/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>New Game Slides</title>
		<link>http://sonargame.com/2011/11/01/new-game-slides/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=new-game-slides</link>
		<comments>http://sonargame.com/2011/11/01/new-game-slides/#comments</comments>
		<pubDate>Tue, 01 Nov 2011 19:52:24 +0000</pubDate>
		<dc:creator>Sean</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://sonargame.com/?p=504</guid>
		<description><![CDATA[Jason Meisel and Sean Middleditch are speakers at the New Game Conference 2011. The slides of our talk are available for everyone on Google Docs: New Game Slides]]></description>
			<content:encoded><![CDATA[<p>Jason Meisel and Sean Middleditch are speakers at the New Game Conference 2011.  The slides of our talk are available for everyone on Google Docs:</p>
<p><a href="https://docs.google.com/presentation/d/110MxOqut_y7KOW1pNwIdcccisIA3ooJwVR-xm-ecuc4/view">New Game Slides</a></p>
]]></content:encoded>
			<wfw:commentRss>http://sonargame.com/2011/11/01/new-game-slides/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Official Release Announcement</title>
		<link>http://sonargame.com/2011/09/05/official-release-announcement/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=official-release-announcement</link>
		<comments>http://sonargame.com/2011/09/05/official-release-announcement/#comments</comments>
		<pubDate>Mon, 05 Sep 2011 21:06:58 +0000</pubDate>
		<dc:creator>Sean</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://sonargame.com/?p=486</guid>
		<description><![CDATA[FOR IMMEDIATE RELEASE Contact: Sean Middleditch – Producer cell: (206) 451-7124 email: sean@sonargame.com SONAR HTML5/WEBGL PUZZLE GAME NOW AVAILABLE IN CHROME WEB STORE REDMOND WA, SEPTEMBER 5th – SONAR is now available in the Chrome Web Store. SONAR is a casual action AI-based puzzle game. The game features an engaging papercraft art style and a [...]]]></description>
			<content:encoded><![CDATA[<p>FOR IMMEDIATE RELEASE</p>
<p>Contact: Sean Middleditch – Producer<br />
cell: (206) 451-7124<br />
email: sean@sonargame.com</p>
<p><b>SONAR HTML5/WEBGL PUZZLE GAME NOW AVAILABLE IN CHROME WEB STORE</b></p>
<p><i>REDMOND WA, SEPTEMBER 5th</i> – SONAR is now available in the Chrome Web Store.  SONAR is a casual action AI-based puzzle game.  The game features an engaging papercraft art style and a charming sense of humor, mixed with casual puzzle game play.  Players are tasked with outsmarting enemy guards using a sound generation device and the Sound Vision Goggles.  SONAR is available at <a href="http://sonargame.com/">http://sonargame.com/</a> for all users of the Chrome web browser.</p>
<p>SONAR is one of the first commercial WebGL games written from the ground up in JavaScript, and is an innovative product that has pushed the limits of what a browser can do with games.  SONAR is free to play and also contains paid for add-on content.  Additional content and the content creation tools are planned for a future release.</p>
<p>The game is based on Subsonic, the innovative DigiPen Institute of Technology student game and IGC 2011 Finalist.  The core development team is comprised of four DigiPen undergraduate students, Sean Middleditch, Jason Meisel, Nick Paavo, and Shawn Pearce.  The art team is comprised of two DigiPen graduates, Megan Noble and Amanda Lien.  The project was completed in just three months during the summer of 2011.</p>
<p>For more information, or to schedule an interview, please contact Sean Middleditch at (206) 451-7124 or sean@sonargame.com.</p>
]]></content:encoded>
			<wfw:commentRss>http://sonargame.com/2011/09/05/official-release-announcement/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>New Game Conference</title>
		<link>http://sonargame.com/2011/08/18/new-game-conference/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=new-game-conference</link>
		<comments>http://sonargame.com/2011/08/18/new-game-conference/#comments</comments>
		<pubDate>Thu, 18 Aug 2011 22:02:54 +0000</pubDate>
		<dc:creator>Sean</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://sonargame.com/blog/?p=274</guid>
		<description><![CDATA[Jason Meisel and Sean Middleditch will be speaking about their experiences developing SONAR at New Game in San Francisco, on November 1st-2nd. The talk will cover the technical challenges we overcame, the new technologies we worked with, the small business and startup hurdles we jumped, and the design and approach we took to building the [...]]]></description>
			<content:encoded><![CDATA[<p>Jason Meisel and Sean Middleditch will be speaking about their experiences developing SONAR at <a href="http://www.newgameconf.com/">New Game</a> in San Francisco, on November 1st-2nd.</p>
<p>The talk will cover the technical challenges we overcame, the new technologies we worked with, the small business and startup hurdles we jumped, and the design and approach we took to building the engine and components.</p>
<p>More information will be available closer to the conference date.</p>
]]></content:encoded>
			<wfw:commentRss>http://sonargame.com/2011/08/18/new-game-conference/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>TarReader.js</title>
		<link>http://sonargame.com/2011/08/12/tarreader-js/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=tarreader-js</link>
		<comments>http://sonargame.com/2011/08/12/tarreader-js/#comments</comments>
		<pubDate>Fri, 12 Aug 2011 07:03:51 +0000</pubDate>
		<dc:creator>Sean</dc:creator>
				<category><![CDATA[Javascript]]></category>

		<guid isPermaLink="false">http://sonargame.com/blog/?p=270</guid>
		<description><![CDATA[In a classic fit of NIH Syndrome, I whipped together a quick JavaScript utility for parsing TAR files (or a common subset of such files, at least), which is released under the MIT Open Source license and is available here: TarReader.js on GitHub. There's no documentation involved just yet, but there's not much to say [...]]]></description>
			<content:encoded><![CDATA[<p>In a classic fit of NIH Syndrome, I whipped together a quick JavaScript utility for parsing TAR files (or a common subset of such files, at least), which is released under the MIT Open Source license and is available here: <a href="https://github.com/subsonicllc/TarReader">TarReader.js on GitHub</a>.<br />
<span id="more-270"></span></p>
<p>There's no documentation involved just yet, but there's not much to say about the API really.  To parse a TAR file, simply create a new instance of the TarReader object and then call either the loadHeaders() or load() method on it, each of which take a string representing the file's raw data.</p>
<p>Note that if you're loading a binary data file like this, you will need to be sure that you are loading the strings as binary data and not as regular UNICODE strings.  If you're using the FileReader facility, you can use the readAsBinaryString() method.  If you're loading a file via XHR, be sure to either use the overrideMimeType('text/plain; charset=x-user-defined') trick or set the responseType to 'blob' (and then use FileReader) to get a binary string of the file.</p>
<p>The TarReader object supports two callbacks, onentry and onload.  onentry is called for each file in the archive, and includes the fields detailed below.  onload is called after the entire file has been loaded.  The TarReader object has the fields files which is an Object mapping file names to entry objects and list which is an Array of entry objects.  Note that if the TAR file has multiple entries with the same name, only the last one will be present in the files field but both will be present in the list field.</p>
<p>The entry objects have several fields.  The most interesting ones are name (the file name), contents (the contents of the file, as a binary string), size (the size of the contents in bytes, which is most useful when you're just reading the headers), and type.  Type can be one of TarReader.FILE, TarReader.DIR, TarReader.SYMLINK, TarReader.HARDLINK, TarReader.CHAR, and TarReader.BLOCK.  There are a few other fields on the entry object such as uid, gui, mode, lastModified, and a few others, but I don't make any guarantees that I'm actually parsing those values correctly at this time, as we do not have a use for them in SONAR.</p>
<p>A good use of this library is to download large sets of files in a single go (such as game assets) which can then be cached in a FileSystem for later use.  Using progress events you can more easily display loading progress than you can with loose files where you don't know the sizes, nor the number of files if you're chain-loading resources.</p>
<p>As the code is MIT licensed, feel free to use for any purpose, fork the code, or send me pull requests on GitHub with fixes, features, tests, or documentation.</p>
]]></content:encoded>
			<wfw:commentRss>http://sonargame.com/2011/08/12/tarreader-js/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Optimizing Vector Usage in JavaScript (and other high-level languages, too)</title>
		<link>http://sonargame.com/2011/08/01/optimizing-vector-usage-in-javascript-and-other-high-level-languages-too/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=optimizing-vector-usage-in-javascript-and-other-high-level-languages-too</link>
		<comments>http://sonargame.com/2011/08/01/optimizing-vector-usage-in-javascript-and-other-high-level-languages-too/#comments</comments>
		<pubDate>Mon, 01 Aug 2011 04:21:11 +0000</pubDate>
		<dc:creator>Sean</dc:creator>
				<category><![CDATA[Javascript]]></category>

		<guid isPermaLink="false">http://sonargame.com/blog/?p=264</guid>
		<description><![CDATA[Our engine is built using the wonderful library written by Brandon Jones. The library is consistently at the top of the benchmark charts for JavaScript linear algebra and graphics libraries. That said, there are a number of interesting things to keep in mind while optimizing use of glMatrix that may not be immediately obvious to [...]]]></description>
			<content:encoded><![CDATA[<p>Our engine is built using the wonderful <a href="http://code.google.com/p/glmatrix/" title="glMatrix"></a> library written by Brandon Jones.  The library is consistently at the top of the benchmark charts for JavaScript linear algebra and graphics libraries.  That said, there are a number of interesting things to keep in mind while optimizing use of glMatrix that may not be immediately obvious to developers who've worked with more conventional C/C++ SIMD vector libraries.<br />
<span id="more-264"></span></p>
<h2>glMatrix Basics</h2>
<p>The first thing to know about glMatrix is that it is not an object-oriented library.  The API is entirely procedural.  It should feel very familiar to users of C-based vector libraries or developers who primarily work in Java or certain other high-level languages that lack operator overloading, but may feel very clunky to C++ developers.</p>
<p>Aspiring JavaScript graphics developers should thus first get accustomed to the procedural nature of glMatrix.  In order to use a glMatrix vector, you first have to create a vector to operate on.  This is done using the vec3.create() function:</p>
<div class="codecolorer-container javascript default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #003366; font-weight: bold;">var</span> ray <span style="color: #339933;">=</span> vec3.<span style="color: #660066;">create</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p>Fairly straight forward.  At this point, you can perform operations on the vector by passing it to one of the functions in the vec3 "namespace" like so:</p>
<div class="codecolorer-container javascript default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">vec3.<span style="color: #660066;">add</span><span style="color: #009900;">&#40;</span>ray<span style="color: #339933;">,</span> <span style="color: #009900;">&#91;</span><span style="color: #CC0000;">1</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">1</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">1</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// add &lt;1,1,1&gt; to ray</span><br />
vec3.<span style="color: #660066;">scale</span><span style="color: #009900;">&#40;</span>ray<span style="color: #339933;">,</span> <span style="color: #CC0000;">4</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// scale the ray by 4</span><br />
vec3.<span style="color: #660066;">negate</span><span style="color: #009900;">&#40;</span>ray<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// negate the ray (point it in the opposite direction)</span></div></td></tr></tbody></table></div>
<p>That's also pretty simple.  An important point to be aware of is that the vec3 operations take an optional destination parameter for most functions.  This parameter (always the last one) is a vector to store the result in.  If this is not given, most functions will treat the first parameter as the destination.  So the commands above could be written (equivalently) as:</p>
<div class="codecolorer-container javascript default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">vec3.<span style="color: #660066;">add</span><span style="color: #009900;">&#40;</span>ray<span style="color: #339933;">,</span> <span style="color: #009900;">&#91;</span><span style="color: #CC0000;">1</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">1</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> ray<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// add &lt;1,1,1&gt; to ray</span><br />
vec3.<span style="color: #660066;">scale</span><span style="color: #009900;">&#40;</span>ray<span style="color: #339933;">,</span> <span style="color: #CC0000;">4</span><span style="color: #339933;">,</span> ray<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// scale the ray by 4</span><br />
vec3.<span style="color: #660066;">negate</span><span style="color: #009900;">&#40;</span>ray<span style="color: #339933;">,</span> ray<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// negate the ray (point it in the opposite direction)</span></div></td></tr></tbody></table></div>
<p>That functionality is important for optimizing your code.  In many cases you will need to take a vector and perform some operations on it to get a new vector, all without modifying the original one.</p>
<p>Note, however, that the destination vector must already exist.  That is, you must call vec3.create() to allocate a vector before passing it to any of the other vec3 functions.</p>
<h2>References</h2>
<p>By far the biggest problem that most developers will run into while simply trying to use the glMatrix library is that all of the vectors are technically objects, and hence are passed and returned by reference rather than by value.  So the following function will have a side-effect on its parameter:</p>
<div class="codecolorer-container javascript default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br /></div></td><td><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #003366; font-weight: bold;">function</span> reflect<span style="color: #009900;">&#40;</span>vec<span style="color: #339933;">,</span> line<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #000066; font-weight: bold;">return</span> vec3.<span style="color: #660066;">subtract</span><span style="color: #009900;">&#40;</span>vec3.<span style="color: #660066;">scale</span><span style="color: #009900;">&#40;</span>line<span style="color: #339933;">,</span> <span style="color: #CC0000;">2</span> <span style="color: #339933;">*</span> vec3.<span style="color: #660066;">dot</span><span style="color: #009900;">&#40;</span>vec<span style="color: #339933;">,</span> line<span style="color: #009900;">&#41;</span> <span style="color: #339933;">/</span> vec3.<span style="color: #660066;">dot</span><span style="color: #009900;">&#40;</span>line<span style="color: #339933;">,</span> line<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> vec<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #003366; font-weight: bold;">var</span> a <span style="color: #339933;">=</span> vec3.<span style="color: #660066;">create</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#91;</span><span style="color: #CC0000;">1</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">1</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">1</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #003366; font-weight: bold;">var</span> b <span style="color: #339933;">=</span> vec3.<span style="color: #660066;">create</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">1</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #003366; font-weight: bold;">var</span> c <span style="color: #339933;">=</span> reflect<span style="color: #009900;">&#40;</span>a<span style="color: #339933;">,</span> b<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p>The code is simply, but it will modify the line vector parameter ('b' in the example above).  The result then is that reflect() modifies its second parameter to be the reflected vector.  Furthermore, in the code above, b and c will reference the same vector at the end.</p>
<p>That's really annoying.  And there's not much you can do about it.  Don't think to fault glMatrix for this behavior, either; it's pretty much a given in JavaScript (and, in fact, almost every other single language in common use, including Python, Java, and Ruby).  Most languages do not allow developers to create user-defined types the way that C++ does, and so all custom types end up being fully heap-allocated objects that are always passed by reference.</p>
<p>It's just something you need to be aware of and to deal with.</p>
<p>A first hack at fixing the above problem might be code like this:</p>
<div class="codecolorer-container javascript default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br /></div></td><td><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #003366; font-weight: bold;">function</span> reflect<span style="color: #009900;">&#40;</span>vec<span style="color: #339933;">,</span> line<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #003366; font-weight: bold;">var</span> rs <span style="color: #339933;">=</span> vec3.<span style="color: #660066;">create</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; vec3.<span style="color: #660066;">scale</span><span style="color: #009900;">&#40;</span>line<span style="color: #339933;">,</span> <span style="color: #CC0000;">2</span> <span style="color: #339933;">*</span> vec3.<span style="color: #660066;">dot</span><span style="color: #009900;">&#40;</span>vec<span style="color: #339933;">,</span> line<span style="color: #009900;">&#41;</span> <span style="color: #339933;">/</span> vec3.<span style="color: #660066;">dot</span><span style="color: #009900;">&#40;</span>line<span style="color: #339933;">,</span> line<span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> rs<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; vec3.<span style="color: #660066;">subtract</span><span style="color: #009900;">&#40;</span>line<span style="color: #339933;">,</span> rs<span style="color: #339933;">,</span> rs<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #000066; font-weight: bold;">return</span> rs<span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #003366; font-weight: bold;">var</span> a <span style="color: #339933;">=</span> vec3.<span style="color: #660066;">create</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#91;</span><span style="color: #CC0000;">1</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">1</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">1</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #003366; font-weight: bold;">var</span> b <span style="color: #339933;">=</span> vec3.<span style="color: #660066;">create</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">1</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #003366; font-weight: bold;">var</span> c <span style="color: #339933;">=</span> reflect<span style="color: #009900;">&#40;</span>a<span style="color: #339933;">,</span> b<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p>That does indeed solve the reference problem.  Neither of the parameters to reflect are modified now, and the test variable c will reference a unique vector rather than being an alias of b.</p>
<p>Unfortunately, this introduces a second problem.  Each call to reflect will now create a new vector object.  This leads us into our next section on garbage collection.</p>
<h2>Garbage Collection</h2>
<p>Most modern languages feature automatic garbage collection of some form, and JavaScript is no exception.  This little marvel is what allows developers to not have to care about memory allocated and deallocation, taking care of everything for you.  Unfortunately, a slightly more cynical (and for our purposes, accurate) way of looking at garbage collection is that it does everything behind your back without your approval.</p>
<p>With a library like glMatrix (or any of its alternatives), each vector is a JavaScript object.  That means it is allocated on the heap and needs to be freed when it is no longer in use.  And that means that the garbage collector has to do all kinds of work to find and free the object.  It also means that the more vectors you create, the more memory will be used until the garbage collector is triggered.  And thus, a tight loop performing some heavy math can trigger a garbage collection run, and that in turn can be deadly for a game's performance if there are a lot of little wasteful objects (like vectors!) floating around.  Even the best collector in the world today can and will impose a noticeable bit of latency in any kind of intense real-time application, like a game or other interactive simulation.</p>
<p>It turns out that you just can't escape the need for a developer to understand and maintain tight control over memory usage, allocation, and deallocation, no matter how high level of a language the developer is working in.  A garbage collector in our case is hurting more than it's helping, but thankfully we can do quite a bit to work around it.</p>
<p>What we need is to drastically reduce the number of vectors we create.  That in turn means being very, very stingy about how often our code is ever allowed to call vec3.create(), or to use any array literal constructs (like [1, 1, 1] in the code above, which creates a new Array object every time it is executed).</p>
<p>Our sample reflect function above has a problem.  Every time it is called, it creates a new vector.  If we were to be using reflect in a loop operating over a few thousand rays, we'd end up creating a few thousand short-lived garbage vectors every time the loop is run.  That's not good.</p>
<p>We can take a page right out glMatrix's own book to fix this, however.</p>
<div class="codecolorer-container javascript default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br /></div></td><td><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #003366; font-weight: bold;">function</span> reflect<span style="color: #009900;">&#40;</span>vec<span style="color: #339933;">,</span> line<span style="color: #339933;">,</span> out<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; vec3.<span style="color: #660066;">scale</span><span style="color: #009900;">&#40;</span>line<span style="color: #339933;">,</span> <span style="color: #CC0000;">2</span> <span style="color: #339933;">*</span> vec3.<span style="color: #660066;">dot</span><span style="color: #009900;">&#40;</span>vec<span style="color: #339933;">,</span> line<span style="color: #009900;">&#41;</span> <span style="color: #339933;">/</span> vec3.<span style="color: #660066;">dot</span><span style="color: #009900;">&#40;</span>line<span style="color: #339933;">,</span> line<span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> out<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; vec3.<span style="color: #660066;">subtract</span><span style="color: #009900;">&#40;</span>line<span style="color: #339933;">,</span> out<span style="color: #339933;">,</span> out<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #000066; font-weight: bold;">return</span> out<span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #003366; font-weight: bold;">var</span> a <span style="color: #339933;">=</span> vec3.<span style="color: #660066;">create</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#91;</span><span style="color: #CC0000;">1</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">1</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">1</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #003366; font-weight: bold;">var</span> b <span style="color: #339933;">=</span> vec3.<span style="color: #660066;">create</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">1</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #003366; font-weight: bold;">var</span> c <span style="color: #339933;">=</span> vec3.<span style="color: #660066;">create</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
reflect<span style="color: #009900;">&#40;</span>a<span style="color: #339933;">,</span> b<span style="color: #339933;">,</span> c<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p>What we've done there is to add a third out parameter to the reflect function.  We're not responsible for creating a vector to pass in, as the example test code does.  At first blush this doesn't look like much of an improvement; all we've done is move the call to vec3.create() from one place to another.</p>
<p>However, let's say we were calling reflect in a loop:</p>
<div class="codecolorer-container javascript default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br /></div></td><td><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #006600; font-style: italic;">// rays is an array of objects with properties a, b, and c, all of which are vectors</span><br />
<span style="color: #003366; font-weight: bold;">function</span> reflect_all<span style="color: #009900;">&#40;</span>rays<span style="color: #339933;">,</span> line<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #000066; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">var</span> i <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">,</span> e <span style="color: #339933;">=</span> rays.<span style="color: #660066;">length</span><span style="color: #339933;">;</span> i <span style="color: #339933;">!=</span> e<span style="color: #339933;">;</span> <span style="color: #339933;">++</span>i<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> ray <span style="color: #339933;">=</span> rays<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; reflect<span style="color: #009900;">&#40;</span>ray.<span style="color: #660066;">a</span><span style="color: #339933;">,</span> ray.<span style="color: #660066;">b</span><span style="color: #339933;">,</span> ray.<span style="color: #660066;">c</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
<p>That new reflect_all function didn't require any new allocations to made at all.  Assuming your data structures are designed with this requirement in mind, you can easily write quite a bit of useful code in a similar fashion.  In other cases, you won't be storing all of your calculations, and you may just need a temporary vector or two.  This can be done by creating these temporaries at the top of the function, outside of any loop, and then reusing those temporaries inside the loop, overwriting their previous values each time.  You can reduce your vector allocations from dozens, hundreds, or thousands down to just several for each such loop.</p>
<h2>Extreme Ninja-like Avoidance of Allocations</h2>
<p>Sometimes you've got to have a few temporaries in a function, and sometimes that function is itself going to be called hundreds or thousands of times.  Those temporaries continue to be a problem that need to be thwarted.  What to do?</p>
<p>One option is to make the temporary variables globals, that are allocated once when your application starts up and never again.  If you're using a module system like node.js's, this isn't too hard.  If you're just using plain JavaScript source files, globals will "pollute" the global namespace and can be a real problem.  You might want to name your temporaries something easy and simple, like tmpv1 and tmpv2, but then you'll easily get conflicts with other source files that create their own same-named temporaries.  You can't easily just share temporaries between different modules, either, because you can't be sure of the scope of a global.</p>
<p>The scope problem is a big issue if you use global at all, so I'm going to cover that in a bit more detail.  Let's say you have a function foo() that calls a function bar().  If both of these functions try to use the same global variable as a temporary value, something bad will happen: bar() will overwrite whatever value foo() had stored in that global.  What this means is that any function using any particular temporary value cannot call or be called by any other function using those same variables.  So globals just aren't safe.</p>
<p>There is a solution, however.  It's to my thinking a little bit of a hack, but others may well consider it a beautiful exposition of the power of JavaScript.  The trick is to create your functions as closures that bind their own temporary values.</p>
<p>Here's an example:</p>
<div class="codecolorer-container javascript default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br /></div></td><td><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #003366; font-weight: bold;">var</span> my_function <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #003366; font-weight: bold;">var</span> tmp <span style="color: #339933;">=</span> vec3.<span style="color: #660066;">create</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>rays<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">var</span> i <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">,</span> e <span style="color: #339933;">=</span> rays.<span style="color: #660066;">length</span><span style="color: #339933;">;</span> i <span style="color: #339933;">!=</span> e<span style="color: #339933;">;</span> <span style="color: #339933;">++</span>i<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// do stuff with tmp and rays[i] </span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p>That code essentially gives the my_function() function its own private "global" variable, with semantics similar to what you'd have with a statically allocated variable in a language like C++.  It allows each function to have the temporaries it needs, allocated once and once only, without any risk of collision with other functions.</p>
<p>Strongly note that there is still a scope problem that can arise in with this trick!  These functions are not re-entrant, which means that they cannot be used for recursive algorithms at all.  This means that if my_function() calls itself -- or calls into another function that eventually calls into my_function() -- then the outer invocation's data stored in its tmp variable will be clobbered by the inner invocation's data.  This trick can thus only be used for functions that do pure computations, and not for any functions that invoke any kind of callback or further processing which might ever call the function again.  In practice, this has not been a problem for any of our own code, but it's something to be very aware of should you choose to use this performance optimization.</p>
<h2>When Nothing Else Works</h2>
<p>Sometimes there's just no getting around the need to create a temporary.  If this is in some outer function that's called a few times at most per frame, that's not much of an issue.  If it's a bit of code that's going to be called many times, though, it's a huge problem.</p>
<p>In these cases, you just have to accept that you can't use glMatrix at all and use hand-rolled code.  In a simple example, you might have to change this code:</p>
<div class="codecolorer-container javascript default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #003366; font-weight: bold;">var</span> v3 <span style="color: #339933;">=</span> vec3.<span style="color: #660066;">create</span><span style="color: #009900;">&#40;</span>v1<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #003366; font-weight: bold;">var</span> d <span style="color: #339933;">=</span> dot<span style="color: #009900;">&#40;</span>v1<span style="color: #339933;">,</span> v2<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
vec3.<span style="color: #660066;">scale</span><span style="color: #009900;">&#40;</span>v3<span style="color: #339933;">,</span> d<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p>into this code:</p>
<div class="codecolorer-container javascript default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br /></div></td><td><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #003366; font-weight: bold;">var</span> x <span style="color: #339933;">=</span> v1.<span style="color: #660066;">x</span><span style="color: #339933;">,</span> y <span style="color: #339933;">=</span> v1.<span style="color: #660066;">y</span><span style="color: #339933;">,</span> z <span style="color: #339933;">=</span> v1.<span style="color: #660066;">z</span><span style="color: #339933;">;</span><br />
d <span style="color: #339933;">=</span> dot<span style="color: #009900;">&#40;</span>v1<span style="color: #339933;">,</span> v2<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
x <span style="color: #339933;">*=</span> d<span style="color: #339933;">;</span><br />
y <span style="color: #339933;">*=</span> d<span style="color: #339933;">;</span><br />
z <span style="color: #339933;">*=</span> d<span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p>It's a lot uglier, and passing those kinds of "vectors" around as parameters is painful, and you really want to avoid doing this if you can, but sometimes you just don't have a choice.</p>
<p>Do note that there are very few alternatives to the ugly code above when you're in this situation.  In particular, do not simply try to create an array or object of your own as a temporary.  Any kind of value other than a boolean, number, or null is going to create a garbage-collected object, and you'd just be doing extra work for absolutely no gain over just using glMatrix directly.</p>
<h2>Other Considerations Besides Vectors</h2>
<p>The last paragraph of the previous section brings up an important point: every single array and object you create will eventually be garbage collected.  Possibly even worse, every array or object you create has to be scanned by the garbage collector (in most implementations) just to see if any <i>other</i> objects are garbage or not.  You want to keep your total object count reasonably low, and not create a lot of garbage objects.</p>
<p>A pattern we initially used in a few too many places in SONAR was to use an object as a way of passing optional parameters to a function.  These functions often had a large number of optional parameters.  Without the params object parameter, their callers looked like this:</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">foo(null, null, null, null, true);<br />
foo(null, player, &quot;physics&quot;, null, true);<br />
foo(25, player);</div></td></tr></tbody></table></div>
<p>That's hard to read (impossible to read if you don't know what the parameters do, in fact) and just as hard to write.  Were JavaScript to offer proper named parameter support, this problem would go away quite nicely.  Unfortunately, JavaScript lacks that capability, so we are stuck improvising.</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">foo({ log : true });<br />
foo({ object : player, component : &quot;physics&quot;, log : true });<br />
foo({ interval : 25, object : player });</div></td></tr></tbody></table></div>
<p>Ignoring that we don't know what foo() actually does, that is quite a bit clearer.  The boolean parameters have a lot clearer meaning, and when we wanted to just pass in that final parameter we didn't have to remember to pass in exactly four nulls first.</p>
<p>Unfortunately, this just doesn't fly for a game in a frequently-called code.  See, now each call to foo() is creating a new temporary object to pass in for its parameters.  We're back to garbage collection problems.</p>
<p>I called out this example because they can be almost invisible to many programmers.  It can be sometimes hard to remember that the object (and array!) literals syntax in JavaScript create a new object each time the relevant line of code is executed.</p>
<p>There aren't many work-arounds.  Simply be aware of the problem, and avoid trying to make short-cuts (even ones that really make the code cleaner) in performance-sensitive code.  Also, help raise awareness in the general Web community as to why having a proper named parameter facility is super important even if the language supports "easy hacks" to simulate them; HTML5 game developers will thank you!</p>
<p>(And while you're at it, help everyone understand why having user-defined stack-allocated pass-by-value types for things like vectors is so critically important, too!)</p>
]]></content:encoded>
			<wfw:commentRss>http://sonargame.com/2011/08/01/optimizing-vector-usage-in-javascript-and-other-high-level-languages-too/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Resource Loading in JavaScript</title>
		<link>http://sonargame.com/2011/07/23/resource-loading-in-javascript/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=resource-loading-in-javascript</link>
		<comments>http://sonargame.com/2011/07/23/resource-loading-in-javascript/#comments</comments>
		<pubDate>Sat, 23 Jul 2011 01:27:17 +0000</pubDate>
		<dc:creator>jason</dc:creator>
				<category><![CDATA[Javascript]]></category>

		<guid isPermaLink="false">http://sonargame.com/blog/?p=55</guid>
		<description><![CDATA[Many of our game assets are -- like in many games -- stored as binary files. JavaScript has relatively recently gained the ability to read binary files, but only with some caveats. Let's go over what it takes to get a simple binary file loaded up into a game. XMLHttpRequest The first problem to solve [...]]]></description>
			<content:encoded><![CDATA[<p>Many of our game assets are -- like in many games -- stored as binary files.  JavaScript has relatively recently gained the ability to read binary files, but only with some caveats.  Let's go over what it takes to get a simple binary file loaded up into a game.<br />
<span id="more-55"></span></p>
<h2>XMLHttpRequest</h2>
<p>The first problem to solve is how to actually load our files into the browser with JavaScript.  We obviously don't have simple File I/O APIs for requesting data from remote sites, and even the newer file storage APIs only work for files we've already saved with those same APIs.  To load an arbitrary file from an arbitrary URL, we've got pretty much just one option: XMLHttpRequest.</p>
<p>The problem is, XMLHttpRequest was really designed for loading (you guessed it) XML.  It also supports plain text quite easily.  Getting arbitrary binary data into it is a bit trickier.  There's a lot of bad or just out-dated advice floating around the Internet, including the use of custom MIME overrides ('text/plain; charset=x-user-defined') and the like.  Thankfully, the newer browsers instead give us a neat work around.  We can explicitly tell our XMLHttpRequest object what response type to use, and we can set this to 'arraybuffer' to get the file loaded up into an ArrayBuffer object.</p>
<div class="codecolorer-container javascript default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br /></div></td><td><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #003366; font-weight: bold;">var</span> xhr <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> XMLHttpRequest<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
xhr.<span style="color: #660066;">responseType</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">'arraybuffer'</span><span style="color: #339933;">;</span><br />
xhr.<span style="color: #000066;">open</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'GET'</span><span style="color: #339933;">,</span> binary_asset_url<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
xhr.<span style="color: #660066;">onreadystatechange</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>xhr.<span style="color: #660066;">readyState</span> <span style="color: #339933;">==</span> <span style="color: #CC0000;">4</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>xhr.<span style="color: #000066;">status</span> <span style="color: #339933;">==</span> <span style="color: #CC0000;">200</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> buffer <span style="color: #339933;">=</span> xhr.<span style="color: #660066;">response</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; process_the_array_buffer<span style="color: #009900;">&#40;</span>buffer<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span> <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #000066;">alert</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'Failed to load file! HTTP status: '</span> <span style="color: #339933;">+</span> xhr.<span style="color: #000066;">status</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span><br />
xhr.<span style="color: #660066;">send</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p>Now we've got the binary file loaded up into an ArrayBuffer.  Unfortunately, we're not done quite yet.</p>
<h2>Typed Array Views</h2>
<p>In theory, we can access parts of our binary file using typed array views, e.g. Float32Array or Uint8Array.  Unfortunately, some browsers are (at the time of writing) suffering from a few bugs with these newer JavaScript APIs.  The one we've run into specifically is that a typed array cannot use a backing ArrayBuffer that isn't sized to a multiple of the typed array element size.  Normally this would be a non-issue when using the proper typed array constructor, but due to the bug a work-around is necessary.</p>
<p>To explain the issue a bit better, say we have a binary 3D mesh file, which consists of a list of vertices (3 floats each) followed by a list of faces (3 Uint16 indices each), and the file also has a header consisting of two Uint16 values (the vertex count and the face count).  To read the data, we might do something like this:</p>
<div class="codecolorer-container javascript default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br /></div></td><td><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #003366; font-weight: bold;">var</span> header <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> Uint16Array<span style="color: #009900;">&#40;</span>mesh_buffer<span style="color: #339933;">,</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">2</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #003366; font-weight: bold;">var</span> number_of_vertices <span style="color: #339933;">=</span> header<span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><br />
<span style="color: #003366; font-weight: bold;">var</span> number_of_faces <span style="color: #339933;">=</span> header<span style="color: #009900;">&#91;</span><span style="color: #CC0000;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #003366; font-weight: bold;">var</span> vertices <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> Float32Array<span style="color: #009900;">&#40;</span>mesh_buffer<span style="color: #339933;">,</span> <span style="color: #CC0000;">4</span><span style="color: #339933;">,</span> number_of_vertices <span style="color: #339933;">*</span> <span style="color: #CC0000;">3</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #003366; font-weight: bold;">var</span> faces <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> Uint16Array<span style="color: #009900;">&#40;</span><span style="color: #CC0000;">4</span> <span style="color: #339933;">+</span> number_of_vertices <span style="color: #339933;">*</span> <span style="color: #CC0000;">12</span><span style="color: #339933;">,</span> number_of_faces <span style="color: #339933;">*</span> <span style="color: #CC0000;">3</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p>However, due to the aforementioned bug, we can get a RangeError exception in this code if the mesh_buffer length is not a multiple of 4, due to the Float32Array constructor essentially ignoring the length parameter (the third parameter).</p>
<p>Our work-around originally was to pad out the ArrayBuffer after reading it in.  This was a bit hairy, however, as there is no way to resize an ArrayBuffer nor is there a particular straight-forward way to copy one ArrayBuffer into another.</p>
<p>What we settled on was to actually to make our mesh exporter plugin for Blender pad the files out as necessary.  Aside from being ever so slightly simpler to implement than padding the buffer in JavaScript, this also means that the overhead (however negligable) of padding out the buffer is performed once offline rather than during asset loading by every player of our game.</p>
<h2>Resource Management</h2>
<p>Now that we've got the bits of code to load an individual file and parse its contents, we have a bigger problem to solve: how do we load and keep track of all these resources?</p>
<p>The first part of the answer is a simple ResourceManager object that tracks resources we've loaded as well as providing a "load filter" mechanism.  The load filter is a means of registering a function for a specific file type/extension that will process the raw binary (or JSON or XML or plain text) files and return an appropriate object that our engine expects.  The mesh loader for instance will parse the binary files, create an object with the vertex_count and face_count properties and arrays for the data, and allocate a WebGL vertex buffer with the data pre-loaded (and indexed).</p>
<p>The resource manager itself just has a simple table of resource names to data files.</p>
<div class="codecolorer-container javascript default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br /></div></td><td><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #003366; font-weight: bold;">function</span> ResourceManager<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">files</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">filters</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
ResourceManager.<span style="color: #660066;">prototype</span>.<span style="color: #660066;">getFile</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #000066;">name</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000066;">name</span> <span style="color: #000066; font-weight: bold;">in</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">files</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">files</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span><br />
<br />
ResourceManager.<span style="color: #660066;">prototype</span>.<span style="color: #660066;">addFile</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #000066;">name</span><span style="color: #339933;">,</span> data<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">files</span><span style="color: #009900;">&#91;</span><span style="color: #000066;">name</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> data<span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span><br />
<br />
ResourceManager.<span style="color: #660066;">prototype</span>.<span style="color: #660066;">addFilter</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>extension<span style="color: #339933;">,</span> filter<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">filters</span><span style="color: #009900;">&#91;</span>extension<span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; extension <span style="color: #339933;">:</span> extension<span style="color: #339933;">,</span><br />
&nbsp; &nbsp; filter <span style="color: #339933;">:</span> filter<span style="color: #339933;">,</span><br />
&nbsp; &nbsp; regex <span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">new</span> RegExp<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'[.]'</span> <span style="color: #339933;">+</span> extension <span style="color: #339933;">+</span> <span style="color: #3366CC;">'$'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'i'</span><span style="color: #009900;">&#41;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span><br />
<br />
ResourceManager.<span style="color: #660066;">prototype</span>.<span style="color: #660066;">filter</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #000066;">name</span><span style="color: #339933;">,</span> data<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #000066; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">var</span> filter <span style="color: #000066; font-weight: bold;">in</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">filters</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">filters</span><span style="color: #009900;">&#91;</span>filter<span style="color: #009900;">&#93;</span>.<span style="color: #660066;">regex</span>.<span style="color: #660066;">test</span><span style="color: #009900;">&#40;</span><span style="color: #000066;">name</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; data <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">filters</span><span style="color: #009900;">&#91;</span>filter<span style="color: #009900;">&#93;</span>.<span style="color: #660066;">filter</span><span style="color: #009900;">&#40;</span>data<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">break</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">files</span><span style="color: #009900;">&#91;</span><span style="color: #000066;">name</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> data<span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p>That's a pretty simplified version of what we use, but it covers the main bases.  The one exercise I'll leave to the reader is how to handle unloading of resources, which is important when a resource might have a handler to a WebGL buffer (as with our mesh resources, for example).</p>
<p>That let's us query loaded files and insert data we already have on hand, but that doesn't solve the problem of actually getting the resources into the engine.  This is where things start to get a bit trickier.</p>
<h2>Batch Loading</h2>
<p>In an ideal world, we'd be loading a packed file with all our assets in it in one go.  This is what the Big Boys do, it's what Flash does, and best of all this is even possible in JavaScript (with a bit of work).  However, this is not particularly convenient during development.  We want to be able to easily swap in and update new assets without needing to run any pack utilities.  Additionally, sometimes you might want multiple pack files, so you can run into the same problems you have when you don't have pack files at all.</p>
<p>The primary problem is loading a list of files using JavaScript's asynchronous APIs and then signaling to the engine that all requested resources have been loaded.  The secondary problem -- and a slightly harder one in some ways -- is making sure this signal is only sent when all dependent resources are loaded.  For instance, an animated character may have several resources required, such as the skinned mesh, animations, and textures.  Going with a nicely data-driven approach, these resource names will not be hard-coded into the engine, but instead will be specified by another reason.  The blueprints file will specify an animated character resource, which in turn specifies the mesh and textures and so on.</p>
<p>What we need then is a system that can take a list of resources, load them, process those files for any dependent resources, and continue loading files until the queue is empty.  Then and only then should the engine be signaled that all resources have been loaded.</p>
<p>Furthermore, actually loading resources can be a bit tricky in places.  For loading most file types, there is only XMLHttpRequest.  For loading unpacked images there is also a regular Image object.  When using XMLHttpRequest, the actual data may be in one of several different properties of the XHR object, including response, responseText, or responseXML.</p>
<p>I'm going to keep things simple for this bit of the article and only cover JSON files.  Extending it to handle binary files (including images), XML, and other formats is not terribly difficult once the core is written.</p>
<p>Our strategy is to build a BatchLoad object that encompasses a queue of resource URLs to load and a callback function.  As each resources loads (or errors out) a modified version of the filter function specified above is run on the loaded data; this modified filter also takes a reference to the BatchLoad object so that it can add additional files to the batch.  After the filter is run, if the queue is empty then the batch is considered complete and callback is invoked.</p>
<div class="codecolorer-container javascript default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br />42<br />43<br />44<br />45<br />46<br />47<br />48<br />49<br />50<br />51<br />52<br />53<br />54<br />55<br />56<br />57<br />58<br /></div></td><td><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #003366; font-weight: bold;">function</span> BatchLoad<span style="color: #009900;">&#40;</span>resource_manager<span style="color: #339933;">,</span> callback<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">resource_manager</span> <span style="color: #339933;">=</span> resource_manager<span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">queue</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">pending</span> <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">callback</span> <span style="color: #339933;">=</span> callback<span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
BatchLoad.<span style="color: #660066;">prototype</span>.<span style="color: #660066;">add</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>file<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">queue</span>.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span>file<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span><br />
<br />
BatchLoad.<span style="color: #660066;">prototype</span>.<span style="color: #660066;">run</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #000066; font-weight: bold;">while</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">queue</span>.<span style="color: #660066;">length</span> <span style="color: #339933;">!=</span> <span style="color: #CC0000;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> file <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">queue</span>.<span style="color: #660066;">pop</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">startLoading</span><span style="color: #009900;">&#40;</span>file<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span><br />
<br />
BatchLoad.<span style="color: #660066;">prototype</span>.<span style="color: #660066;">startLoading</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>file<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #003366; font-weight: bold;">var</span> self <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; <span style="color: #003366; font-weight: bold;">var</span> xhr <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> XMLHttpRequest<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; xhr.<span style="color: #000066;">open</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'GET'</span><span style="color: #339933;">,</span> file<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; xhr.<span style="color: #660066;">overrideMimeType</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'application/json'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; xhr.<span style="color: #660066;">responseType</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">'json'</span><span style="color: #339933;">;</span><br />
&nbsp; xhr.<span style="color: #660066;">onreadystatechange</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>xhr.<span style="color: #660066;">readystate</span> <span style="color: #339933;">==</span> <span style="color: #CC0000;">4</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>xhr.<span style="color: #000066;">status</span> <span style="color: #339933;">==</span> <span style="color: #CC0000;">200</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">try</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> data <span style="color: #339933;">=</span> JSON.<span style="color: #660066;">parse</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">responseText</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; data <span style="color: #339933;">=</span> self.<span style="color: #660066;">resource_manager</span>.<span style="color: #660066;">filter</span><span style="color: #009900;">&#40;</span>file<span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span>data<span style="color: #339933;">:</span> data<span style="color: #339933;">,</span> batch<span style="color: #339933;">:</span> self<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; self.<span style="color: #000066;">onLoad</span><span style="color: #009900;">&#40;</span>file<span style="color: #339933;">,</span> data<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span> <span style="color: #000066; font-weight: bold;">catch</span> <span style="color: #009900;">&#40;</span>e<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; self.<span style="color: #000066;">onError</span><span style="color: #009900;">&#40;</span>file<span style="color: #339933;">,</span> e<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span> <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; self.<span style="color: #000066;">onError</span><span style="color: #009900;">&#40;</span>file<span style="color: #339933;">,</span> <span style="color: #3366CC;">'http status '</span> <span style="color: #339933;">+</span> xhr.<span style="color: #000066;">status</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">pending</span><span style="color: #339933;">++;</span><br />
&nbsp; xhr.<span style="color: #660066;">send</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span><br />
<br />
BatchLoad.<span style="color: #660066;">prototype</span>.<span style="color: #000066;">onLoad</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>file<span style="color: #339933;">,</span> data<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">resource_manager</span>.<span style="color: #660066;">addFile</span><span style="color: #009900;">&#40;</span>file<span style="color: #339933;">,</span> data<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">--</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">pending</span> <span style="color: #339933;">==</span> <span style="color: #CC0000;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">callback</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span><br />
<br />
BatchLoad.<span style="color: #660066;">prototype</span>.<span style="color: #000066;">onError</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>file<span style="color: #339933;">,</span> msg<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'Failed to load resource: '</span> <span style="color: #339933;">+</span> file <span style="color: #339933;">+</span> <span style="color: #3366CC;">', because '</span> <span style="color: #339933;">+</span> msg<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">--</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">pending</span> <span style="color: #339933;">==</span> <span style="color: #CC0000;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">callback</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p>Using this is relatively simple.  Our core engine has a few files it depends on.  The object manager loads up our blueprints.json file, our graphics system has dependencies on world tiles, the UI system has dependencies on an layout XML file, and the campaign manager has a dependency on our campaign.json.  Almost everything else is loaded as a dependency of one of those files.</p>
<p>The core engine creates a BatchLoad object and passes it off to each system component of the engine.  Then it calls the run() method, and the callback is what starts up the engine's main loop (via the requestAnimationFrame() function).</p>
<p>We have filters set up for our character file format, for our blueprints file, and for a few other key assets.  The blueprints filter doesn't actually change the blueprints JSON file any, but instead it scans the defined blueprints and their components and passes the component data off to a preLoad(batch) method on related component constructor.  This method can then use its knowledge of the component field data to add files to the batch.  For example, the "mesh3d" component's preLoad() method knows that the the "texture" property value should be queued up as a request for assets/textures/[texture].png.</p>
]]></content:encoded>
			<wfw:commentRss>http://sonargame.com/2011/07/23/resource-loading-in-javascript/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Improvise, Adapt and Overcome</title>
		<link>http://sonargame.com/2011/07/22/improvise-adapt-and-overcome/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=improvise-adapt-and-overcome</link>
		<comments>http://sonargame.com/2011/07/22/improvise-adapt-and-overcome/#comments</comments>
		<pubDate>Fri, 22 Jul 2011 02:05:17 +0000</pubDate>
		<dc:creator>mnoble</dc:creator>
				<category><![CDATA[Art]]></category>

		<guid isPermaLink="false">http://sonargame.com/blog/?p=219</guid>
		<description><![CDATA[Over the past several weeks, we had easy but ugly.  Creating assets as placeholders for what was to come.  This week has begun the process of replacing those mock-ups with what will really be in game. Here I mocked up some simple low-poly models I sketched and rigged in Blender.  The purpose of this was [...]]]></description>
			<content:encoded><![CDATA[<p>Over the past several weeks, we had easy but ugly.  Creating assets as placeholders for what was to come.  This week has begun the process of replacing those mock-ups with what will really be in game.</p>
<p>Here I mocked up some simple low-poly models I sketched and rigged in Blender.  The purpose of this was to get all necessary animations mocked up so that only the file would need to be replaced as I made new ones.  In other programs, it is also simpler to edit the mesh on the rig and replace the weights.  Not so in Blender.  It's definitely good to know there is going to be a hiccup so that you can plan around it, which is why working on multiple art assets can be quite useful.</p>
<div id="attachment_222" class="wp-caption alignnone" style="width: 310px"><a href="http://sonargame.com/blog/wp-content/uploads/2011/07/models.jpg"><img class="size-medium wp-image-222 " src="http://sonargame.com/blog/wp-content/uploads/2011/07/models-300x284.jpg" alt="roughs" width="300" height="284" /></a><p class="wp-caption-text">rough 3d sketches</p></div>
<p>The down side is that it can look quite unfinished and ugly.   There is another upside, which is being able to make changes as you go along, and discover whole new possibilities as you work.  I find this to be much more fun than trying to make everything fit to a single idea.  Of course, the artist always has to keep in mind the overall visual style, and there is a stopping point, which we are quick approaching.</p>
<div id="attachment_220" class="wp-caption alignleft" style="width: 310px"><a href="http://sonargame.com/blog/wp-content/uploads/2011/07/drawoverorig.jpg"><img class="size-medium wp-image-220" src="http://sonargame.com/blog/wp-content/uploads/2011/07/drawoverorig-300x300.jpg" alt="testing blender models and textures" width="300" height="300" /></a><p class="wp-caption-text">ugly but effective</p></div>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>Here's an example of testing assets before you get to the final product.</p>
<div id="attachment_221" class="wp-caption alignleft" style="width: 310px"><a href="http://sonargame.com/blog/wp-content/uploads/2011/07/drawover.jpg"><img class="size-medium wp-image-221" src="http://sonargame.com/blog/wp-content/uploads/2011/07/drawover-300x300.jpg" alt="painted still" width="300" height="300" /></a><p class="wp-caption-text">painting over the real thing</p></div>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>And then exploring to see how we really want this to look.</p>
<p>The current sprint will see finalized character models and well close to done animations and UI.  In order to be able to finish both 2D and 3D assets by the deadline, we've pulled in another artist with strong 2D and UI skills.  A lot of work has gone into finalizing concepts for the look of the game.  The next few images are some of the best ideas from those pages.</p>
<p><a href="http://sonargame.com/blog/wp-content/uploads/2011/07/femalechar_2.jpg"><img class="alignleft size-medium wp-image-223" src="http://sonargame.com/blog/wp-content/uploads/2011/07/femalechar_2-300x284.jpg" alt="" width="300" height="284" /></a><a href="http://sonargame.com/blog/wp-content/uploads/2011/07/malechar_1.jpg"><img class="alignleft size-medium wp-image-224" src="http://sonargame.com/blog/wp-content/uploads/2011/07/malechar_1-300x250.jpg" alt="" width="300" height="250" /></a><a href="http://sonargame.com/blog/wp-content/uploads/2011/07/malechar_2.jpg"><img class="alignleft size-medium wp-image-225" src="http://sonargame.com/blog/wp-content/uploads/2011/07/malechar_2-300x178.jpg" alt="" width="300" height="178" /></a></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><a href="http://sonargame.com/blog/wp-content/uploads/2011/07/watch1.jpg"><img class="alignleft size-medium wp-image-226" src="http://sonargame.com/blog/wp-content/uploads/2011/07/watch1-300x221.jpg" alt="" width="300" height="221" /></a>    <a href="http://sonargame.com/blog/wp-content/uploads/2011/07/watch2.jpg"><img class="alignleft size-medium wp-image-227" src="http://sonargame.com/blog/wp-content/uploads/2011/07/watch2-300x284.jpg" alt="" width="300" height="284" /></a></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>As we both work furiously on getting final designs, colors, tiles, backgrounds, animations, models and all other things that are art related done, there is very little time to dilly-dally.  We  look forward to being able to take you through the entire process in the next blog post at the end of this sprint.</p>
]]></content:encoded>
			<wfw:commentRss>http://sonargame.com/2011/07/22/improvise-adapt-and-overcome/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>WebGL Art Pipeline: Exporting from Blender</title>
		<link>http://sonargame.com/2011/07/09/webgl-art-pipelines-and-so-can-you/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=webgl-art-pipelines-and-so-can-you</link>
		<comments>http://sonargame.com/2011/07/09/webgl-art-pipelines-and-so-can-you/#comments</comments>
		<pubDate>Sat, 09 Jul 2011 02:14:14 +0000</pubDate>
		<dc:creator>jason</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://sonargame.com/blog/?p=206</guid>
		<description><![CDATA[When making a game engine, one of your primary concerns is art. How do you create assets? How do you get them into the game? How can you streamline the whole process? When developing SONAR's art pipeline, we had a few things to consider: We're a very small development team. We have 2 artists, 3 [...]]]></description>
			<content:encoded><![CDATA[<p>When making a game engine, one of your primary concerns is art. How do you create assets? How do you get them into the game? How can you streamline the whole process?</p>
<p>When developing SONAR's art pipeline, we had a few things to consider:</p>
<ul>
<li>We're a very small development team. We have 2 artists, 3 programmers, and 1 designer. This means there is very little barrier to communication.</li>
<li>We have very little time to go from nothing to a fully featured game. Thus, we can't spend a lot (or, really, any) time polishing the engine or pipeline any more than critically necessary.</li>
<li>WebGL is a very new and very limited platform. We needed to keep everything as simple as possible in order to ensure a smooth, integrated pipeline.</li>
</ul>
<p><span id="more-206"></span></p>
<h2>Blender</h2>
<p>After weighing our options, we decided to use <a href="blender.org">Blender</a> as our core 3D tool. Blender is capable of both modelling and animation, I was personally familiar with it from previous projects, and it gives Python scripts access to all the data we would need. Whether or not we'd use Blender in retrospect... is not the purpose of this blog post. However, the first thing we would need is to get meshes from Blender into the game engine.</p>
<p>The first thing I realized is that Blender 2.5 has very little documentation when it comes to its Python interface. The official <a href="http://www.blender.org/documentation/blender_python_api_2_57_release/contents.html">documentation</a> is definitely useful to see what exists, but the data Blender offers is very cumbersome to correctly utilize. Luckily for you, I'm going to explain how. Another resource that you should have ready is the built-in Unreal Engine exporter, which you can find in <span style="text-decoration: underline;">&lt;blender&gt;/2.57/scripts/addons/io_export_unreal_psk_psa.py</span>.</p>
<h2>Scripting</h2>
<div class="codecolorer-container python default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br /></div></td><td><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">bpy.<span style="color: black;">ops</span>.<span style="color: #008000;">object</span>.<span style="color: black;">mode_set</span><span style="color: black;">&#40;</span>mode<span style="color: #66cc66;">=</span><span style="color: #483d8b;">&quot;EDIT&quot;</span><span style="color: black;">&#41;</span><br />
<br />
bpy.<span style="color: black;">ops</span>.<span style="color: black;">mesh</span>.<span style="color: black;">select_all</span><span style="color: black;">&#40;</span>action<span style="color: #66cc66;">=</span><span style="color: #483d8b;">&quot;SELECT&quot;</span><span style="color: black;">&#41;</span><br />
bpy.<span style="color: black;">ops</span>.<span style="color: black;">mesh</span>.<span style="color: black;">quads_convert_to_tris</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
<br />
bpy.<span style="color: black;">ops</span>.<span style="color: #008000;">object</span>.<span style="color: black;">mode_set</span><span style="color: black;">&#40;</span>mode<span style="color: #66cc66;">=</span><span style="color: #483d8b;">&quot;OBJECT&quot;</span><span style="color: black;">&#41;</span><br />
<br />
obj <span style="color: #66cc66;">=</span> bpy.<span style="color: black;">context</span>.<span style="color: black;">active_object</span><br />
mesh <span style="color: #66cc66;">=</span> obj.<span style="color: black;">to_mesh</span><span style="color: black;">&#40;</span>bpy.<span style="color: black;">context</span>.<span style="color: black;">scene</span><span style="color: #66cc66;">,</span> <span style="color: #008000;">True</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'PREVIEW'</span><span style="color: black;">&#41;</span></div></td></tr></tbody></table></div>
<p>This code assumes you have the mesh you want to export selected. It then converts any quads in the mesh to tris (which is necessary for our in-engine format, which we'll discuss later). Finally, it captures the mesh after applying modifiers (that True parameter).</p>
<div class="codecolorer-container python default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br /></div></td><td><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">vertices <span style="color: #66cc66;">=</span> mesh.<span style="color: black;">vertices</span><br />
faces <span style="color: #66cc66;">=</span> mesh.<span style="color: black;">faces</span><br />
faces_uvs <span style="color: #66cc66;">=</span> mesh.<span style="color: black;">uv_textures</span>.<span style="color: black;">active</span>.<span style="color: black;">data</span><br />
<br />
<span style="color: #ff7700;font-weight:bold;">def</span> getUV<span style="color: black;">&#40;</span>face_index<span style="color: #66cc66;">,</span> vert_index<span style="color: black;">&#41;</span>:<br />
&nbsp; <span style="color: #ff7700;font-weight:bold;">return</span> faces_uvs<span style="color: black;">&#91;</span>face_index<span style="color: black;">&#93;</span>.<span style="color: black;">uv</span><span style="color: black;">&#91;</span>vert_index<span style="color: black;">&#93;</span></div></td></tr></tbody></table></div>
<p>Now, I just get references to the vertices, faces, and uv data from the mesh. This will fail if the mesh doesn't have UVs (in which case, just skip that). Each face is a list of indices into the vertices list. The UVs are slightly more complicated: the index into faces can be used to index faces_uvs to get a similar list of UVs for each vertex, using the same index as vertices. I simplify access with a function similar to getUV.</p>
<div class="codecolorer-container python default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br /></div></td><td><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">class</span> Vertex:<br />
&nbsp; <span style="color: #ff7700;font-weight:bold;">pass</span><br />
out_verts <span style="color: #66cc66;">=</span> <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span><br />
<br />
<span style="color: #ff7700;font-weight:bold;">for</span> f_uv<span style="color: #66cc66;">,</span> face <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">enumerate</span><span style="color: black;">&#40;</span>faces<span style="color: black;">&#41;</span>:<br />
&nbsp; <span style="color: #ff7700;font-weight:bold;">for</span> v_uv<span style="color: #66cc66;">,</span> vi <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">enumerate</span><span style="color: black;">&#40;</span>face.<span style="color: black;">vertices</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; vert <span style="color: #66cc66;">=</span> Vertex<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; vert.<span style="color: black;">uv</span> <span style="color: #66cc66;">=</span> getUV<span style="color: black;">&#40;</span>f_uv<span style="color: #66cc66;">,</span> v_uv<span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; vert.<span style="color: black;">pos</span> <span style="color: #66cc66;">=</span> vertices<span style="color: black;">&#91;</span>vi<span style="color: black;">&#93;</span>.<span style="color: black;">co</span><br />
&nbsp; &nbsp; vert.<span style="color: black;">normal</span> <span style="color: #66cc66;">=</span> vertices<span style="color: black;">&#91;</span>vi<span style="color: black;">&#93;</span>.<span style="color: black;">normal</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; out_verts<span style="color: black;">&#91;</span>vi<span style="color: black;">&#93;</span> <span style="color: #66cc66;">=</span> vert</div></td></tr></tbody></table></div>
<p>Next, I make an empty Vertex class that I use to store each vertex's data in a format closer to the one I will then output to file. I also create a dictionary to store these vertices in. I would use a list, but a dictionary using the vertex index as a key will ensure the vertices are all unique.</p>
<p>Then, I iterate through each vertex in each face. I create the Vertex object, store the data about that vertex, and add it to the dictionary. Pretty simple.</p>
<h2>Mesh Format</h2>
<p>From there, it's about outputting this data to a file. I have created both JSON and binary exporters, and honestly JSON is the better way to go. It's significantly simpler to get into a Javascript game engine (binary file loading will be a future blog post). It's also easier to read and write (it's such a simple format, there's no need for specialized tools). Really, it's just the way to go.</p>
<p>Specifically, I simply store this data as one giant Array of floats. This Array is structured the same exact way as the Float32Array I end up binding to an ArrayBuffer in WebGL in the engine. Simple. Simple simple simple.</p>
<h2>Animation, Into the Engine, and More!</h2>
<p>Obviously, this is just step 1 of many in our pipeline. Future blog posts will almost certainly focus on: skinned meshes, animation systems, binary file loading, resource loading, resource management, and oh so much more. If you have any suggestions for future articles or any questions about what I've talked about here, post about it in the comments!</p>
]]></content:encoded>
			<wfw:commentRss>http://sonargame.com/2011/07/09/webgl-art-pipelines-and-so-can-you/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Component Based Game Objects in JavaScript</title>
		<link>http://sonargame.com/2011/06/28/component-based-game-objects-in-javascript/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=component-based-game-objects-in-javascript</link>
		<comments>http://sonargame.com/2011/06/28/component-based-game-objects-in-javascript/#comments</comments>
		<pubDate>Tue, 28 Jun 2011 03:17:31 +0000</pubDate>
		<dc:creator>Sean</dc:creator>
				<category><![CDATA[Javascript]]></category>

		<guid isPermaLink="false">http://sonargame.com/blog/?p=98</guid>
		<description><![CDATA[Component based game engines are all the rage these days, and for good reasons. Engines like Unity3D, Crytek, and Crafty are all at least partially compositional. Where the traditional OOP inheritance model usually falls apart in many large projects (as many of the JavaScripters out there who are taking refuge from Java and C# likely [...]]]></description>
			<content:encoded><![CDATA[<p>Component based game engines are all the rage these days, and for good reasons.  Engines like <a href="http://unity3d.com/">Unity3D</a>, <a href="http://www.crytek.com/">Crytek</a>, and <a href="http://craftyjs.com/">Crafty</a> are all at least partially compositional.  Where the traditional OOP inheritance model usually falls apart in many large projects (as many of the JavaScripters out there who are taking refuge from Java and C# likely already know), a compositional object model is actually quite powerful and flexible.  JavaScript makes it dead easy to implement such a system, thankfully.  I'm going to go over the basics.<br />
<span id="more-98"></span></p>
<h2>Traditional Inheritance</h2>
<p>The traditional inheritance model used in many OOP projects stems from a deep misunderstanding of the purpose of objects and interfaces.  Classical examples of how inheritance works are taught in schools that illustrate relationships like "a dog is a mammal is an animal" which implies a hierarchy of relationships between types.  Programmers will implement a model that includes three classes, one for Animal, one for Mammal, and one for Dog.  Another branch of the tree might be Gecko which inherits from Reptile which inherits from Animal.  This works okay-ish in a small project with a few classes, but then the programmer eventually needs to add Platypus to the project and the entire hierarchy becomes a huge design problem.  Methods and data members that originally could be confined to a particular branch the tree (like LayEgg in Reptile) ends up moving into the base Animal class (because now one of the Mammals needs it, too).  Eventually that base class becomes full of dozens of methods and members that only a tiny fraction of its derived classes ever need but which simply cannot be put anywhere.</p>
<p>The problem in such an example is not that classical OOP facilities are bad but rather that they have been used incorrectly.  Real-world relationships and objects were modeled in code rather than modeling the abstract behaviors and interfaces that the real-world objects are built from.  Programmers are taught to "write to the abstraction" everywhere else, and that's exactly what makes sense for objects as well.  Instead of having a subclass of Animal called Reptile that adds a LayEgg method, and a Mammel subclass that has a LiveBirth method, it makes more sense to add a new Reproduction interface with a single Reproduce method and to then write egg-based and non-egg-based implementations of that interface.</p>
<p>With the inheritance model, however, we're still stuck wondering where exactly to put these interface implementation objects.  Each animal instance needs one and only one.  The specific implementation chosen is dependent on the type of animal.  We could come up with a complex system of virtual methods and multiple-inheritance to fix this, or we can use compositions.</p>
<h2>Compositions</h2>
<p>The compositional model solves the above problem by simply allowing the base object class to contain a list of other objects that implement various bits of functionality.  In our above case, we'd have a single Animal object, and it would not have any derived classes.  It also wouldn't implement much functionality at all, either.  Instead, each Animal contains a list of objects that implement the IComposition interface (any likely some other interface as well) each of which for satisfies an individual behavioral requirement.  For each real-world animal we wish to model we would simply create an Animal object and add all of the necessary components to it that the animal needs to function.  Each Animal might have a single component that implements ILocomotion, which could be any one of Bipedal, Quadrupedal, Snakelike, etc.</p>
<p>Notably, as there are no derived classes from the core base object, that means that we don't have an object constructor to create specific objects.  There is no Dog class that could create all of the necessary components at initialization time.  We can make up for this by simply creating some functions (or special factory objects) for creating each specific type of object, of course, but that would cause us to lose the second huge advantage of compositions: data-driven object building.</p>
<p>Unlike the inheritance model, compositional objects can be created by designers and editors rather than only by coders.  Let's replace our animal metaphor with something more game relevant.  We're going to have a base GameObject class and components for PhysicsBody, DrawableMesh, Gun, TargettingAI, ChasingAI, etc.  We are making a game where the player can build units to defend an area: an RTS or a tower defense game of some kind.</p>
<p>The designer asks for a unit that has a Gun and shoots to the right and a tank that can chase enemies and shoot at them.  This is very easy to accomplish by simply giving each of these units the proper components.  Both units would need a Gun component, but only the tank needs the ChasingAI component and TargettingAI component.  This can all be specified in a data-driven approach without any coder needing to be involved.</p>
<p>The structure of the units could also be build easily with inheritance, of course, right up until the designer asks for a tower that targets enemies.  Now all the TargettingAI that would be in the Tank class (which might derive from a MobileUnit class that derives from BaseUnit) also needs to be in TargettingTower (which is derived from TowerUnit that derives from BaseUnit), so it ends up being moved into the BaseUnit.  Which must be done by a coder.  Composition avoids both of those problems, the first by allowing TargettingAI to be added to any game object and the second by allowing the designer to just add the TargettingAI component to the unit definitions in the game editor rather than needing to request a programmer to do so.</p>
<h2>Archetypes</h2>
<p>Archetypes (also commonly known as prototypes, but we'll avoid that term as JavaScript already has a different idea of what a prototype is; I personally also like to call them blueprints) are the definition of a spawnable game object, including it's components and their default properties.  In the above example, we might have archetypes like "tank", "simple_tower", and "targetting_tower".  These are loaded from a data file, and can be easily edited by designers, either by hand or with a friendly graphical tool.</p>
<p>With JavaScript, it's easy to define an archetype using JSON.  Our file that describes all our known archetypes looks something like the following (an excerpt from SONAR's archetypes.json file):</p>
<div class="codecolorer-container javascript default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br /></div></td><td><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #3366CC;">&quot;slow_guard&quot;</span> <span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #3366CC;">&quot;transform&quot;</span> <span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; <span style="color: #3366CC;">&quot;perception&quot;</span> <span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #3366CC;">&quot;distance&quot;</span> <span style="color: #339933;">:</span> &nbsp;<span style="color: #CC0000;">4.0</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #3366CC;">&quot;angle&quot;</span> <span style="color: #339933;">:</span> <span style="color: #CC0000;">30.0</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; <span style="color: #3366CC;">&quot;physics&quot;</span> <span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #3366CC;">&quot;type&quot;</span> <span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;circle&quot;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #3366CC;">&quot;radius&quot;</span> <span style="color: #339933;">:</span> <span style="color: #CC0000;">0.5</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; <span style="color: #3366CC;">&quot;ai&quot;</span> <span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #3366CC;">&quot;behaviors&quot;</span> <span style="color: #339933;">:</span> <span style="color: #009900;">&#91;</span> <span style="color: #3366CC;">&quot;guard&quot;</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">&quot;chase&quot;</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">&quot;search&quot;</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">&quot;script&quot;</span> <span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #3366CC;">&quot;speed&quot;</span> <span style="color: #339933;">:</span> <span style="color: #CC0000;">2.0</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #3366CC;">&quot;stun&quot;</span> <span style="color: #339933;">:</span> <span style="color: #CC0000;">5.0</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; <span style="color: #3366CC;">&quot;drawable3d&quot;</span> <span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #3366CC;">&quot;mesh&quot;</span> <span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;meshes/slow_guard.mesh&quot;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span><br />
&nbsp; <span style="color: #3366CC;">&quot;player&quot;</span> <span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #3366CC;">&quot;transform&quot;</span> <span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; <span style="color: #3366CC;">&quot;physics&quot;</span> <span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; <span style="color: #3366CC;">&quot;drawable3d&quot;</span> <span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #3366CC;">&quot;mesh&quot;</span> <span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;meshes/player.mesh&quot;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
<p>That example defines two archetypes, one for slow_enemy and one for player.  The data inside specifies the components of the archetype (the keys) and the component parameters (the value).  Components that have no parameters to specify just have an empty object as data.</p>
<p>Being data driven, this lets our designer add new enemy types or tweak existing ones very easily.  If the slow_guard speed turns out to be too slow during a play test session, for instance, the designer can just bump that value up and carry on without needing to dig in code or ask a coder to make the change.  (In a traditional C/C++ engine, this also saves the need to recompile!)</p>
<h2>Level Files</h2>
<p>There's an additional benefit to having a system that parses a JSON file to load components and values, too, which is making it amazingly easy to customize individual units in our level files.  We merge object definitions from our level files with the archetypes they "inherit" from to create a single game object definition that we pass into our game object factory.</p>
<p>Let's take a look at a level file fragment:</p>
<div class="codecolorer-container javascript default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br /></div></td><td><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #3366CC;">&quot;title&quot;</span> <span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;Level 1&quot;</span><span style="color: #339933;">,</span><br />
&nbsp; <span style="color: #3366CC;">&quot;tiles&quot;</span> <span style="color: #339933;">:</span> <span style="color: #009900;">&#91;</span> ... <span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span><br />
<br />
&nbsp; <span style="color: #3366CC;">&quot;objects&quot;</span> <span style="color: #339933;">:</span> <span style="color: #009900;">&#91;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #3366CC;">&quot;archetype&quot;</span> <span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;slow_enemy&quot;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #3366CC;">&quot;transform&quot;</span> <span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #3366CC;">&quot;position&quot;</span> <span style="color: #339933;">:</span> <span style="color: #009900;">&#91;</span> <span style="color: #CC0000;">4.5</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">3.5</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">0.0</span> <span style="color: #009900;">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #3366CC;">&quot;archetype&quot;</span> <span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;slow_enemy&quot;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #3366CC;">&quot;transform&quot;</span> <span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #3366CC;">&quot;position&quot;</span> <span style="color: #339933;">:</span> <span style="color: #009900;">&#91;</span> <span style="color: #CC0000;">8.5</span><span style="color: #339933;">,</span><span style="color: #CC0000;">43.5</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">0.0</span> <span style="color: #009900;">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #3366CC;">&quot;ai&quot;</span> <span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #3366CC;">&quot;script&quot;</span> <span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;patrol1&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #3366CC;">&quot;archetype&quot;</span> <span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;player&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #3366CC;">&quot;transform&quot;</span> <span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #3366CC;">&quot;position&quot;</span> <span style="color: #339933;">:</span> <span style="color: #009900;">&#91;</span> <span style="color: #CC0000;">7.5</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">2.5</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">0.0</span> <span style="color: #009900;">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; <span style="color: #009900;">&#93;</span><br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
<p>The definition for each object includes an archetype name and a list of components and properties, just like the archetype definition file.  Essentially all we do during level initialization is look up the archetype for each of these objects, merge the archetype definition and the object definition from the level file, and then pass that object to the game object factory.</p>
<p>The most basic use of this is for specifying position in our level editor.  The editor can override the default position of the Transform component (which specifies position, rotation, and scale) with the position the object should spawn at.  With a few exceptions this is about all we do in our particular game; as a puzzle game, we need a high amount of conformity between enemies and objects to make the puzzles understandable and predictable.  In a more action-oriented game, however, it may be interesting to be able to specify equipment or weapon systems or other stats on a per-object basis.</p>
<h2>The Code</h2>
<p>In a C/C++ engine, there'd be an awful lot of boilerplate to make all this happen.  In JavaScript, it's all pretty simple.  Let's just jump on in with a sample game object and component type that we might use in a simple game engine.  The following code is a simplified example, but illustrates the basic concepts of what we're doing in SONAR.</p>
<div class="codecolorer-container javascript default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br />42<br />43<br />44<br />45<br />46<br />47<br />48<br />49<br /></div></td><td><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #003366; font-weight: bold;">function</span> GameObject<span style="color: #009900;">&#40;</span>descriptor<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">components</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
GameObject.<span style="color: #660066;">prototype</span>.<span style="color: #660066;">event</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #000066;">name</span><span style="color: #339933;">,</span> params<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #006600; font-style: italic;">// &quot;guess&quot; name of the event handler</span><br />
&nbsp; <span style="color: #003366; font-weight: bold;">var</span> handler_name <span style="color: #339933;">=</span> <span style="color: #3366CC;">'on'</span> <span style="color: #339933;">+</span> <span style="color: #000066;">name</span>.<span style="color: #660066;">charAt</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">toUpper</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #000066;">name</span>.<span style="color: #660066;">slice</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; <span style="color: #006600; font-style: italic;">// invoke event handler in each component if it exists</span><br />
&nbsp; <span style="color: #000066; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">var</span> i <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">,</span> e <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">components</span>.<span style="color: #660066;">length</span><span style="color: #339933;">;</span> i <span style="color: #339933;">!=</span> e<span style="color: #339933;">;</span> <span style="color: #339933;">++</span>i<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> component <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">components</span><span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>handler_name <span style="color: #000066; font-weight: bold;">in</span> component <span style="color: #339933;">&amp;&amp;</span> <span style="color: #000066; font-weight: bold;">typeof</span> component<span style="color: #009900;">&#91;</span>handler_name<span style="color: #009900;">&#93;</span> <span style="color: #339933;">==</span> <span style="color: #3366CC;">'function'</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; component<span style="color: #009900;">&#91;</span>handler_name<span style="color: #009900;">&#93;</span>.<span style="color: #660066;">call</span><span style="color: #009900;">&#40;</span>component<span style="color: #339933;">,</span> params<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span><br />
<br />
GameObject.<span style="color: #660066;">factory</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>descriptor<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #006600; font-style: italic;">// get the archetype descriptor</span><br />
&nbsp; <span style="color: #003366; font-weight: bold;">var</span> components <span style="color: #339933;">=</span> clone<span style="color: #009900;">&#40;</span>window.<span style="color: #660066;">archetypes</span><span style="color: #009900;">&#91;</span>descriptor.<span style="color: #660066;">archetype</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; <span style="color: #006600; font-style: italic;">// merge the descriptor with the archetype</span><br />
&nbsp; <span style="color: #000066; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">var</span> <span style="color: #000066;">name</span> <span style="color: #000066; font-weight: bold;">in</span> descriptor<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// only merge component descriptors</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">typeof</span> descriptor<span style="color: #009900;">&#91;</span><span style="color: #000066;">name</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">==</span> <span style="color: #3366CC;">'object'</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; components<span style="color: #009900;">&#91;</span><span style="color: #000066;">name</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> merge<span style="color: #009900;">&#40;</span>components<span style="color: #009900;">&#91;</span><span style="color: #000066;">name</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> descriptor<span style="color: #009900;">&#91;</span><span style="color: #000066;">name</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; <span style="color: #006600; font-style: italic;">// create the object</span><br />
&nbsp; <span style="color: #003366; font-weight: bold;">var</span> obj <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> GameObject<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; <span style="color: #006600; font-style: italic;">// actually create the components</span><br />
&nbsp; <span style="color: #000066; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">var</span> <span style="color: #000066;">name</span> <span style="color: #000066; font-weight: bold;">in</span> descriptor<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// &quot;guess&quot; the name of the component constructor</span><br />
&nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> type_name <span style="color: #339933;">=</span> <span style="color: #000066;">name</span>.<span style="color: #660066;">charAt</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">toUpper</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #000066;">name</span>.<span style="color: #660066;">slice</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">1</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #3366CC;">'Component'</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// construct the component</span><br />
&nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> component <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> type_name<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span><span style="color: #339933;">,</span> descriptor<span style="color: #009900;">&#91;</span><span style="color: #000066;">name</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// register the component by name and in our ordered list</span><br />
&nbsp; &nbsp; obj<span style="color: #009900;">&#91;</span><span style="color: #000066;">name</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> component<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; obj.<span style="color: #660066;">components</span>.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span>component<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; <span style="color: #006600; font-style: italic;">// send a &quot;create&quot; event to all our components</span><br />
&nbsp; <span style="color: #006600; font-style: italic;">// signaling that the whole object is created</span><br />
&nbsp; obj.<span style="color: #660066;">event</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'create'</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p>It's not too bad at all.</p>
<p>The GameObject type handles construction of the components on the game object.  We have a factory function on the GameObject constructor (rather than a per-instance method) that takes the object data loaded from our level file.  It looks up the archetype's base component definitions, and merges those with the individual object definition.  This is passed to the GameObject constructor to create all our components and initialize them.</p>
<p>The event method is a simple thing that gives our game components a way of processing game logic events.  The GameObject handler simply forwards its events to the components.</p>
<p>Various components handle different events as they see fit.  Components like the TransformComponent doesn't process any events, as it's simply a data holder that is used by other components.  The Physics component will respond to several events, notably the update event, which is sent to every game object once per frame with the frame time; the physics component would do integration in response to this event.</p>
]]></content:encoded>
			<wfw:commentRss>http://sonargame.com/2011/06/28/component-based-game-objects-in-javascript/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
