PhobosLab http://www.phoboslab.org/log Latest news en What the requestAnimationFrame API Should Have Looked Like http://www.phoboslab.org/log/2012/05/what-the-requestanimationframe-api-should-have-looked-like <p>Chrome, Firefox and IE10 now support <a href="https://developer.mozilla.org/en/DOM/window.requestAnimationFrame">requestAnimationFrame</a> – a noble idea, with a totally backwards API.</p> <p>Imagine you have this JavaScript <em>animation</em> that you want to <em>constantly</em> update. An animation that <em>constantly</em> updates, needs to be updated more than once, i.e. <em>constantly</em>. After all it's an animation. So why on earth do I have an API to request <em>one</em> update at a time?</p> <p>Mozilla's <a href="https://developer.mozilla.org/en/DOM/window.requestAnimationFrame#section_1">documentation</a> even warns developers that the API might not work as expected:</p> <blockquote> <p>Note: Your callback routine must itself call requestAnimationFrame() unless you want the animation to stop.</p> </blockquote> <p>Ah, yes.</p> <p>Car analogy time: I have this very nice car that makes a beeping noise whenever I open the door with the ignition off and the headlights still on. You know, to warn me that my headlights might run the battery dry in my absence. <em>&quot;Thank you car, that's very kind of you. But let me ask you something: why didn't you just turn the headlights off yourself instead of notifying me?&quot;</em></p> <p>The <code>requestAnimationFrame</code> API is modeled after <a href="https://developer.mozilla.org/en/DOM/window.setTimeout">setTimeout</a> when it should've been modeled after <a href="https://developer.mozilla.org/en/DOM/window.setInterval">setInterval</a> instead.<br/></p> <p>Here's my proposal:</p> <pre> <span class="C">// Install an animation that continously calls the callback </span><span class="K">var</span> animationId = setAnimation( callback, element ); <span class="C">// Stop the animation </span>clearAnimation( animationId ); </pre> <p>And the code to make this happen:</p> <pre> (<span class="K">function</span>(w) { <span class="S">&quot;use strict&quot;</span>; <span class="C">// Find vendor prefix, if any </span> <span class="K">var</span> vendors = [<span class="S">'ms'</span>, <span class="S">'moz'</span>, <span class="S">'webkit'</span>, <span class="S">'o'</span>]; <span class="K">for</span>( <span class="K">var</span> i = <span class="N">0</span>; i &lt; vendors.length &amp;&amp; !w.requestAnimationFrame; i++ ) { w.requestAnimationFrame = w[vendors[i]+<span class="S">'RequestAnimationFrame'</span>]; } <span class="C">// Use requestAnimationFrame if available </span> <span class="K">if</span>( w.requestAnimationFrame ) { <span class="K">var</span> next = <span class="N">1</span>, anims = {}; w.setAnimation = <span class="K">function</span>( callback, element ) { <span class="K">var</span> current = next++; anims[current] = <span class="K">true</span>; <span class="K">var</span> animate = <span class="K">function</span>() { <span class="K">if</span>( !anims[current] ) { <span class="K">return</span>; } <span class="C">// deleted? </span> w.requestAnimationFrame( animate, element ); callback(); }; w.requestAnimationFrame( animate, element ); <span class="K">return</span> current; }; w.clearAnimation = <span class="K">function</span>( id ) { <span class="K">delete</span> anims[id]; }; } <span class="C">// [set/clear]Interval fallback </span> <span class="K">else</span> { w.setAnimation = <span class="K">function</span>( callback, element ) { <span class="K">return</span> w.setInterval( callback, <span class="N">1000</span>/<span class="N">60</span> ); } w.clearAnimation = w.clearInterval; } }(window)); </pre> <p><a href="https://gist.github.com/2624768">Gist</a> on Github</p> Mon, 07 May 2012 00:04:46 +0200 http://www.phoboslab.org/log/2012/05/what-the-requestanimationframe-api-should-have-looked-like JavaScript on the XBox 360 http://www.phoboslab.org/log/2012/04/javascript-on-the-xbox-360 <p>Yes, it works. No, it's not very fast.</p> <p>As a part of my <a href="http://impactjs.com/">HTML5 Game Engine</a> I previously wrote a framework that lets you run a JavaScript/Canvas game on the iPhone without using the browser engine, drawing everything in OpenGL directly. This worked out pretty well. The <a href="http://itunes.apple.com/us/app/biolab-disaster/id433062854">iOS version</a> of Biolab Disaster is indistinguishable from natives apps.</p> <p><img class="center" src="http://www.phoboslab.org/files/images/biolab-xbox.jpg" alt=""/> <em>My HTML5 Game <a href="http://playbiolab.com">Biolab Disaster</a> running on the XBox 360</em></p> <p>I wanted to do the same for the Xbox360 – how hard could it be? I got a JavaScript engine running on iOS, so I'm used to jumping through hoops, but nothing could prepare me for what I was up to.</p> <p>Microsoft offers a <a href="http://create.msdn.com/en-US/">developer program</a> for the XBox 360, where you can write games in C# with a framework called XNA. These games are compiled into NET bytecode and work on Windows and the XBox without any modifications. However, in contrast to Windows, you can't execute <em>unmanaged</em> code on the XBox. This ruled out all the popular JavaScript engines that are written in C++, such as V8 or JavaScriptCore.</p> <p>Luckily, a guy called Paul Bartrum wrote <a href="http://jurassic.codeplex.com/">Jurassic</a> - a JavaScript engine for NET. It compiles JavaScript code into NET bytecode at runtime, allowing far better performance than a pure interpreter (e.g. <a href="http://jint.codeplex.com/">Jint</a>). It works almost seamlessly with C# classes and fully supports the ECMAScript 5 standard. I wrote some quick code to get Biolab Disaster up and running with Jurassic and XNA on Windows and got a steady 60hz with lots of headroom.</p> <p>But there's a catch: Even though Jurassic is written in C#, it doesn't work on the XBox. The XBox doesn't run the <em>real</em> NET Framework, but something called NET CF or Compact Framework. The functionality to create bytecode at runtime (&quot;Reflection.Emit&quot;) is completely missing.</p> <p>Now here's is where it gets funky. If Jurassic can compile JavaScript at runtime, I should be able to rig it to compile everything into a NET Assembly at compile time. The XBox then only needs to load this Assembly (a DLL) and execute it. I pitched my idea to Paul Bartrum:</p> <blockquote> <p>It seems doable, though I think you underestimate the work required to generate the assembly</p> </blockquote> <p>I sure did.<br/></p> <p>Fast forward three weeks of me trying to wrap my head around C# – a language I've never worked with – modifying a real world compiler – something I had no knowledge of whatsoever – and sitting for hours in the debugger, stepping through the code line by line.</p> <p>I finally got it working. The Biolab Disaster Title screen came on my TV. Smoothly animated and in glorious 1cm pixels. I pressed a button to start the game and was greatly disappointed to see it running with only 3 frames per second.</p> <p>After a bit of profiling, I found no obvious bottleneck. The compiled JavaScript code was just slow overall. Good enough for <em>some</em> scripting, but not for a whole game. Maybe I'm missing something that makes the compiled JavaScript so much slower on the XBox. A certain operation that has to be &quot;emulated&quot; by the NET CF; something that requires extensive 64bit math? I don't know. I called it quits.</p> <p>I put all the sources and small JavaScript demo on GitHub. It should compile and run out of the box on Windows and the XBox 360 with the <a href="http://www.microsoft.com/en-us/download/details.aspx?displaylang=en&amp;id=27570">Windows Phone SDK</a> (don't be fooled by the name, it includes the XBox stuff as well).</p> <p><a href="https://github.com/phoboslab/JS360">JS360 on Github</a></p> <p>If anyone from Microsoft is reading this: Don't be Apple. Give us a speedy JavaScript engine as part of XNA.<br/> </p> Fri, 27 Apr 2012 19:55:41 +0200 http://www.phoboslab.org/log/2012/04/javascript-on-the-xbox-360 Hate IE with a Passion http://www.phoboslab.org/log/2012/03/hate-ie-with-a-passion <p>There's no denial that HTML5 Gaming is going to be huge. It was a big topic at this year's GDC and there's an <a href="https://twitter.com/#!/phoboslab/status/179407462699503616">arcade machine running an HTML5 game</a> currently at SXSW. I've been at <a href="http://future-of-mobile.com/london-2011">Future of Mobile</a> and <a href="http://ongamestart.com/">onGameStart</a> last year, giving some insight and showing off my <a href="http://impactjs.com/">Game Engine</a>. HTML5 Gaming is here to stay.</p> <p>In my talk at onGameStart I had a short section <em>dedicated</em> to Internet Explorer: I apologized to the one guy from Microsoft in the audience - then switched to a slide stating &quot;Hate IE with a Passion&quot; and a next one showing the IE logo with a speech bubble, proclaiming &quot;Please kill me!&quot;, disgustingly set in Comic Sans because &quot;IE doesn't deserve a better font&quot;.<br/></p> <iframe src="http://player.vimeo.com/video/32155296?color=ffffff" width="500" height="281" frameborder="0"></iframe> <div><em>The part about IE is 26 minutes in.</em></div> <p>But wait, didn't I say in an <a href="http://www.phoboslab.org/log/2011/08/are-we-fast-yet">earlier post</a> that IE9 works great with my Game Engine?</p> <blockquote> <p>IE9's smoothness on the other hand is remarkable. Of all browsers and systems I tested, IE9 subjectively produced the best results.</p> </blockquote> <p>IE9 was a huge leap forward from IE8 and all the things that are implemented in IE9 work pretty well. There are some problems with &lt;Audio&gt;, but they are not as disastrous as they were with Chrome and Firefox a few month ago. And Microsoft's implementation of the &lt;Canvas&gt; element is one of the fastest around. IE9 is a solid browser.</p> <p>So where's the problem?</p> <p>It's all the things that IE9 doesn't do. And I'm not talking about some <em>nice to have</em> features, but Microsoft's general attitude. They pretty much ensure that IE will always stay obsolete and be every developer's last choice. Here's how.</p> <h2>Auto Updates and Release Cycle</h2> <p>This is a big one. IE8 was released in March 2009, IE9 in March 2011 - two years later. There's no release date for IE10 yet, but it will take at least until March next year. Microsoft has finally decided to have <a href="http://www.geek.com/articles/geek-pick/microsoft-decides-to-automatically-update-internet-explorer-for-everyone-20111215/">some sort of auto update</a>, but it will leave a lot of users behind. It will take years until all IE users have updated.</p> <p>Compare this with the Chrome and Firefox guys: they release a new version every 6 weeks now. And the best thing - users don't even notice. Chrome's update mechanism is truly invisible to the average user. If you're doing some cutting edge web stuff, you no longer have to say &quot;works in Chrome 17&quot;, but just &quot;works in Chrome&quot;. Nobody cares about the version number, because everyone is always on the newest version, or at most two versions behind.</p> <p>From a developers standpoint, this is invaluable. It brings us certainty. We can be sure that any feature that was added 12 weeks ago has now arrived for the vast majority of users.</p> <p>Not so with IE. Paul Irish recently had a beautiful article <a href="http://paulirish.com/2011/browser-market-pollution-iex-is-the-new-ie6/">about the clusterfuck that is Microsoft's lifecycle policy</a>. It's just sad.</p> <h2>&lt;Video&gt; and &lt;Audio&gt; Codecs</h2> <p>Firefox, Chrome and Opera support the open source WebM and Ogg Theora video codecs and the open source Ogg Vorbis audio codec. IE supports none of these.</p> <p>I know WebM is controversial, but damn, they are Microsoft. They should be able to come up with a solution that's good for the web: Buy the MPEG-LA and release all h264 patents in the public domain; improve WebM; invent a new, open video codec. Whatever, just do something.</p> <p>With Ogg Vorbis I can't even think of single reason not to support it. Over the last few month I asked a few guys from Microsoft why they don't support Ogg Vorbis - nobody could give me an answer. Nobody knows. Maybe we are not complaining loud enough?</p> <h2>WebAudio, Fullscreen, Mouslock…</h2> <p>There are ongoing efforts to implement better <a href="http://chromium.googlecode.com/svn/trunk/samples/audio/index.html">audio APIs</a>, <a href="https://wiki.mozilla.org/Gecko:FullScreenAPI">fullscreen support</a>, <a href="https://sites.google.com/a/chromium.org/dev/developers/design-documents/mouse-lock">mouse lock</a> (all desperately needed for games) and a whole bunch of other stuff. And browser vendors are working together to form a common standard - yet, Microsoft is curiously absent from these discussions.</p> <p>Of course IE will support those features eventually. Maybe in version 11 or 12, after every other major browser made it clear that these are useful and important. Then it will take another 3-4 years for IE users to update. So we can safely use the fullscreen API for IE in about 6 years. Awesome.</p> <p>Microsoft should spark those discussions instead of trying to catch up years later.</p> <p>IE is slowing everyone down and makes your life as a developer more complicated. It actively prevents progress. Microsoft just looks at what everyone else does, implements the bare minimum they need in order to not be completely ignored and annoys us with a yearly update cycle and millions of users unable or unaware to update. This is not how the web works.</p> <p>I wrote this post because I <em>still</em> care about IE - I <em>still</em> haven't given up completely.<br/></p> <p>What can you do? Force Microsoft to fix IE or let it die?</p> <p>Hate IE with a passion!</p> Wed, 14 Mar 2012 17:28:35 +0100 http://www.phoboslab.org/log/2012/03/hate-ie-with-a-passion Are We Fast Yet? http://www.phoboslab.org/log/2011/08/are-we-fast-yet <p>Mozilla constantly asks this question, but <a href="http://arewefastyet.com/">their answer</a> really doesn't tell us all that much. Yes, JavaScript has been getting faster and faster and the <em>v8bench</em>, <em>kraken</em> and <em>sunspider</em> benchmarks are a good indicator for that. Yet, they all miss some issues that are quite important for HTML5 Gaming.</p> <p>One of these issues was made blatantly obvious when I finished work on the performance graph for the <a href="http://playbiolab.com/?debug">new debug menu</a> in my <a href="http://Impactjs.com/">JavaScript Game Engine</a>: Garbage Collector pauses.<br/></p> <p>All JavaScript engines periodically run a Garbage Collector to release unused memory. In some cases this GC step can take several hundred milliseconds, in which the game comes to a complete halt. Even if that only happens every 600 frames, or 10 seconds, it's far more annoying than a game that runs at a lower, but constant framerate.<br/></p> <p><img class="center" src="http://www.phoboslab.org/files/images/impact-debug-menu.png" alt="Impact Debug Menu"/> <em>Performance Graph for Firefox 6 – the orange spikes indicate GC pauses</em></p> <p>GC pauses have been a huge problem with Firefox 3.6 and Firefox 6 is still the worst offender here. Other browsers have shorter GC pauses, but there's still room for improvement. To gain some more insight, I constructed a new benchmark that essentially simulates a playthrough for a game level.<br/></p> <p>Give it a try at <a href="http://html5-benchmark.com">HTML5-Benchmark.com</a>.</p> <p>Now, to be clear, this benchmark is very <em>“opinionated”</em>. It's by no means a complete benchmark for all HTML5 features, but only tests one very specific use case: smooth running games rendered with the <code>&lt;canvas&gt;</code> element. It's a very real use case though; not an average for hundreds or thousands of small tests.</p> <p>The score for the HTML5-Benchmark takes the total time the browser spent rendering frames and a big penalty for pauses into account (the exact formula is <code>1000000/(sqrt(totalTime) + lagTime * 0.1)</code>). The benchmark automatically runs at a “reasonable” screen size - i.e. a screen size that makes sense for a game on the particular device. Thus, the final score is a real indicator for the browser's ability to smoothly run HTML5 games.</p> <p><a href="http://www.phoboslab.org/files/images/html5-benchmark-scores.png" rel="whitebox"><img class="center" src="http://www.phoboslab.org/cache/thumbs/500x330/files/images/html5-benchmark-scores.jpg" alt="HTML5-Benchmark Scores"/></a></p> <p>A score of about 1500 means the game is playable. Note that the benchmark actually runs a bit slower on mobile devices than the game itself. This is because the game utilizes a special pre-rendered background mode on mobile devices, but doesn't do so in the benchmark to keep the scores comparable.</p> <p>It's almost comical how bad the Android's Browser performed in my tests: the Samsung Galaxy Tab 10.1 is actually <em>slower</em> than a four year old 1st gen iPod Touch. Firefox 4 on the same tablet performs a lot better though.</p> <p>The desktop version of Firefox 6 still suffers a lot from the occasional GC pauses. This makes Firefox the last choice if you want to enjoy HTML5 games. The performance <em>decrease</em> from the stable Chrome 13 to the dev version of Chrome 15 is quite strange too. It may have to do something with the new hardware acceleration for Canvas' 2d context.</p> <p><img class="center" src="http://www.phoboslab.org/files/images/impact-benchmark.jpg" alt="Impac Benchmark"/></p> <p>There are some things that the benchmark can't measure. Opera for instance has a very steady timing and never misses a frame. On my machine however, the benchmark still looks choppy - probably because the benchmark's timer isn't synchronized with the refresh rate of the display. Opera essentially renders frames that it never displays. The new <a href="https://developer.mozilla.org/en/DOM/window.mozRequestAnimationFrame">requestAnimationFrame()</a> could fix this, but it hasn't arrived in all browsers yet.</p> <p>IE9's smoothness on the other hand is remarkable. Of all browsers and systems I tested, IE9 subjectively produced the best results. It seems to precisely synchronize JavaScript execution with the refresh rate: the benchmark runs at exactly 60 FPS on my machine, even though the timer is scheduled every 16 milliseconds, or 62.5 FPS.</p> <p>This leads me to ask a few questions: shouldn't browser vendors concentrate on fixing <code>setInterval()</code> first, before implementing <code>requestAnimationFrame()</code>? And shouldn't it behave more like <code>setInterval()</code> instead of <code>setTimeout()</code>? That is – I don't want to call a function to schedule each and every frame I want to draw, but just call it once and let the browser schedule the frames.</p> <p><code>requestAnimationFrame()</code> looks good on paper, but it doesn't actually produce visually better results than <code>setInterval()</code> in those browsers that implement it.<br/></p> <p>On my machine, Chrome 13 and Firefox 6 awkwardly jump between 120 and 60 FPS when using it (it's disabled in the benchmark) and even without GC pauses there are noticeable hiccups, while IE9 is able to produce perfectly smooth animations without it. At the moment <code>requestAnimationFrame()</code> is truly worthless for games.</p> <p>So, no – we aren't fast yet. But we're getting there.</p> Thu, 11 Aug 2011 02:17:06 +0200 http://www.phoboslab.org/log/2011/08/are-we-fast-yet JavaScriptCore Project Files for iOS http://www.phoboslab.org/log/2011/06/javascriptcore-project-files-for-ios <p>Some weeks ago <a href="http://www.phoboslab.org/log/2011/04/ios-and-javascript-for-real-this-time">I released</a> a compiled version of the JavaScriptCore library for iOS as part of my <a href="http://impactjs.com/">game engine</a>. Since then I had many people asking for the project files necessary to build the library - and I promised to release them as well. But before I do so, let me just rant about Apple's politics real quick:</p> <p>They suck.</p> <p>You see, JavaScriptCore is an Open Source library. In fact the whole <a href="http://www.webkit.org/">WebKit project</a> is. It's licensed under BSD and LGPL licenses. The latter of which requires that if you modify the software you have to release your modified version – including the complete source – under the LGPL as well. Furthermore, it <a href="http://www.opensource.org/licenses/lgpl-2.1.php">states</a>: <em>&quot;For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, <strong>plus the scripts used to control compilation and installation of the library</strong>.&quot;</em></p> <p>Yet the JavaScriptCore sources that you get from <a href="http://opensource.apple.com/source/JavaScriptCore/JavaScriptCore-721.26/">Apple's Open Source page</a> come without a project file. So while you get the source code for the library, it's useless because you can't compile it.</p> <p>Luckily you can also get the current JavaScriptCore sources directly from the <a href="http://svn.webkit.org/repository/webkit/trunk/Source/JavaScriptCore/">SVN repository</a> – and behold, they even come with an Xcode project file, ready to be build for MacOSX with the touch of a button. But – and here's the kicker – this project file curiously misses the iOS platform target. You can't build it for the iPhone or iPad.</p> <p>Adding this iOS target to the project file is by no means a trivial endeavor, mind you. Especially not in Xcode. I ended up duplicating the MacOSX target, setting the <code>Base SDK</code> to <code>Latest iOS</code>, changing the <code>Supported Platforms</code> to <code>iphoneos iphonesimulator</code> and poking around in the project file with a text editor to change the <code>productType</code> to <code>library.static</code>, because you're not allowed to build a <code>framework</code> for iOS.</p> <p>After some more changes that I can't remember (I'll be sure to document this next time I do it), I was finally able to compile the library for iOS. I submitted my game <a href="http://itunes.apple.com/us/app/biolab-disaster/id433062854">Biolab Disaster</a> to the App Store only to see that it was rejected the next day.</p> <p>JavaScriptCore utilizes the libicucore library to sort strings in a unicode fashion. Apparently libicucore is a &quot;private&quot; API on iOS – which is curious because I can add this library to my iOS project without any dirty hacks, I'm just not allowed to use any functions of it. So I compiled JavaScriptCore again, this time setting the <code>UCONFIG_NO_COLLATION</code> preprocessor macro to disable unicode sorting.</p> <p>Did I mention Apple's politics suck?</p> <p>Anyway, here's the statically compiled <code>libiOSJavaScriptCore.a</code> that you can use in your iOS projects and the source and project file if you want to build it yourself for whatever reason:</p> <ul> <li><a href="http://www.phoboslab.org/files/jsc/libiOSJavaScriptCore-534.27.zip">libiOSJavaScriptCore-534.27.zip</a> – compiled library</li> <li><a href="http://www.phoboslab.org/files/jsc/iOSJavaScriptCore-534.27.zip">iOSJavaScriptCore-534.27.zip</a> – source code and project file</li> </ul> <p>This all is based on the slightly outdated 534.27 version of JavaScriptCore, but at least this version seems to be AppStore compatible.</p> <h3>Using libiOSJavaScriptCore.a in your Project:</h3> <ul> <li>Copy the JavaScriptCore directory with the header files from the ZIP to your project folder and add them to your Xcode project</li> <li>Copy the libiOSJavaScriptCore.a into your project folder</li> <li>Add the <code>libstdc++.dylib</code>, <code>libicucore.dylib</code> from the list and the <code>libiOSJavaScriptCore.a</code> from &quot;Add other...&quot; <a href="http://stackoverflow.com/questions/3352664/how-to-add-existing-frameworks-in-xcode-4/3377682#3377682">like so</a></li> <li><code><h>import &lt;JavaScriptCore/JavaScriptCore.h&gt;</code></li> </ul> <h3>Building JavaScriptCore from the Source:</h3> <ul> <li>Select <em>iOSJavaScriptCore iPhone</em> as the active Scheme and build</li> <li>Select <em>iOSJavaScriptCore iPhone Simulator</em> as the active Scheme and build</li> <li>Navigate your terminal to the build directory: depending on your Xcode settings either <code>build/Products/</code> directly in your project directory or <code>~/Library/Developer/Xcode/DerivedData/JavaScriptCore-xxx/Build/Products/</code> </li> <li>Combine the ARM6/7 and x86 (Simulator) libs into one: <code>lipo -create Production-iphoneos/libiOSJavaScriptCore.a Production-iphonesimulator/libiOSJavaScriptCore.a -output libiOSJavaScriptCore.a</code></li> </ul> <p>Btw.: AppCelerator <a href="https://github.com/appcelerator/webkit_titanium/tree/master/Source/JavaScriptCore">maintains their own version of JavaScriptCore</a> that they use in Titanium, but I have no idea how to build it. Any hints are greatly appreciated!</p> <p>If you want to support me, please consider buying a license of <a href="http://impactjs.com/">my game engine</a>. It also makes a great gift ;-) </p> Mon, 13 Jun 2011 23:32:54 +0200 http://www.phoboslab.org/log/2011/06/javascriptcore-project-files-for-ios iOS and JavaScript - for Real this Time! http://www.phoboslab.org/log/2011/04/ios-and-javascript-for-real-this-time <p>Less talk, more action – Apple just approved two of my JavaScript games for the AppStore: <a href="http://itunes.apple.com/us/app/biolab-disaster/id433062854">Biolab Disaster</a> and <a href="http://itunes.apple.com/us/app/drop-js/id433062287">Drop</a>. Both are free; go check them out. You can also play them in your browser <a href="http://playbiolab.com/">here</a> and <a href="http://impactjs.com/drop/">here</a>.<br/></p> <p>Both games are pretty simple (the <a href="http://impactjs.com/documentation/drop-source-code">source</a> for Drop is only 300 odd lines long) and written with my JavaScript Game Engine <a href="http://impactjs.com/">Impact</a>.</p> <p>These are certainly not the first games written in JavaScript to be available in the AppStore. Tools like <a href="http://www.appmobi.com/">AppMobi</a>, <a href="http://www.phonegap.com/">PhoneGap</a> or <a href="http://www.appcelerator.com/">Titanium</a> make it easy to bundle some HTML pages and JavaScript together in an App and display them in a UIWebView, which is basically just a browser window (<strong>correction:</strong> Titanium doesn't use a UIWebView but instead has some native bindings). Games written with Impact already work okay-ish in the iPhone's browser and thus also in AppMobi and PhoneGap.</p> <p>So what's so special about these two games now? They don't use PhoneGap or Titanium. They don't even use a UIWebView. Instead, they bypass the iPhone's browser altogether and use Apple's JavaScript interpreter (JavaScriptCore) directly. All graphics are rendered with OpenGL instead of in a browser window and all sound and music is played back with OpenAL instead of… well, having <a href="http://www.phoboslab.org/log/2011/03/the-state-of-html5-audio">no sound at all</a>.</p> <p>What makes this possible is a compatibility layer that mimics the HTML5 Canvas and Audio APIs but is implemented with OpenGL and OpenAL behind the scenes. Think of it as a browser that can only display a Canvas element and play Audio elements, but does not render generic HTML pages. A browser perfectly suited for HTML5 games.</p> <p>This means you can take your JavaScript games written for Impact and run them on iOS with perfect sound and touch input and way better drawing performance than with Mobile Safari. Now, to be clear, I only implemented a bare minimum of the Canvas API - just enough to be able to run Impact. The whole thing is still in a very experimental state.</p> <p>If you have a license for Impact you will find the complete source code for this all on your <a href="http://impactjs.com/download/">download page</a>. I also wrote some <a href="http://impactjs.com/documentation/ios/overview">basic documentation</a> to get you started. In theory, you don't have to know anything about Objective-C to use this, but at this stage some Objective-C knowledge will sure come in handy. Again, this is very experimental. Don't expect it to work at all.</p> <p>If you've been following this blog for a while, you might remember a <a href="http://www.phoboslab.org/log/2010/10/impact-for-ios">post from October 2010</a> where I attempted the exact same thing. Back then I used the JavaScriptCore library that is already available on iOS and used by Apple in Mobile Safari. The problem was, that this library is &quot;private&quot;, meaning that Apple does not want you to use it. And since you can't publish anything in the AppStore that uses private libraries I abandoned the idea.</p> <p>However I recently revisited the project, because there was still a chance to make this work: JavaScriptCore is a part of the open source WebKit project. Instead of using the private library that comes with iOS, you <em>theoretically</em> could compile your own version of this library and bundle it together with your App. Which is exactly what I did.</p> <p>Since Apple does not provide any project files to compile JavaScriptCore for iOS (presumably to annoy us) and JavaScriptCore itself uses some of iOS' private APIs, compiling this beast into a static library - in an App Store compatible fashion - took me a few days.<br/></p> <p>I also had to make a small sacrifice: JavaScriptCore uses libicu to sort strings according to a unicode locale. Sadly, libicu is also private on iOS and bundling it is not an option because of its size. So I got rid of libicu completely. This means that only ASCII strings are now sorted correctly (e.g. the umlaut &quot;Ä&quot; will come after &quot;Z&quot;, not after &quot;A&quot; as it should). Other than that, the JavaScript library should behave exactly as the private one that comes with iOS.</p> <p>Also, the JavaScriptCore library bundled with iOSImpact does <strong>not</strong> use the JIT compiler (Nitro). You can't allocate executable memory on the iPhone and if Apple doesn't lift that restriction, there's nothing I can do about it. However, Apple recently made an exception for Mobile Safari – <em>if</em> they would make their JavaScriptCore API public, they probably <em>could</em> enable the JIT for everyone. That's a big <code>if</code> though; I don't see it happening, because Apple loves native code (Objective-C) and hates scripting languages.</p> <p>I was afraid Apple would reject the two games for some obscure reason, but they didn't. Which leaves me to wonder why the JavaScriptCore library that comes with iOS is private in the first place. Bundling JavaScriptCore with your App adds about 2MB in size – not much, but I fail to see how this can be in Apple's interest.</p> <p>Anyway, the performance of both games is pretty good. I still get some occasional slowdowns (~20fps) on my iPhone3GS in Biolab Disaster when there are too many particles on the screen, but it remains playable at all times. It's also nice to have perfectly working sound on iOS now - something even some desktop browsers still struggle with.</p> Wed, 27 Apr 2011 10:02:28 +0200 http://www.phoboslab.org/log/2011/04/ios-and-javascript-for-real-this-time Multiple Channels for HTML5 Audio http://www.phoboslab.org/log/2011/03/multiple-channels-for-html5-audio <p>Now that I've calmed down a bit after my <a href="http://www.phoboslab.org/log/2011/03/the-state-of-html5-audio">The State of HTML5 Audio</a> article, let's see if can actually write something productive.</p> <p>Here's the deal: for a typical game you may have a sound effect that you want to play very often. In <a href="http://playbiolab.com">Biolab Disaster</a> the sound of your plasma gun is such an effect. This particular sound has a length of 0.6 seconds, but you sure can mash the shoot button quicker than 1.66 times per second – so to not interrupt the plasma sound each time you press the button, but instead play a <em>new</em> sound we need to have multiple sound “channels”.</p> <p><a href="http://www.phoboslab.org/log/2011/03/multiple-channels-for-html5-audio">Read complete post &raquo;</a></p> Fri, 11 Mar 2011 02:04:52 +0100 http://www.phoboslab.org/log/2011/03/multiple-channels-for-html5-audio The State of HTML5 Audio http://www.phoboslab.org/log/2011/03/the-state-of-html5-audio <p>When I started to work on my <a href="http://impactjs.com">JavaScript Game Engine</a> back in October 2009, the biggest problems I encountered were with the new HTML5 Audio Element. The Canvas Element already worked nicely in all browsers that supported it at the time, albeit some were a little slow.<br/></p> <p>Now, in 2011, the rendering performance for Canvas has been improved dramatically, audio however is still broken in large parts. I think it is time for a change in tone. Be warned, there's some profanity ahead because HTML5 Audio is still <strong>that fucked up</strong>.</p> <p>Before we start, you may want to play a quick round of <a href="http://playbiolab.com/">Biolab Disaster</a> or <a href="http://www.phoboslab.org/ztype/">Z-Type</a> and have a look at a simple <a href="http://www.phoboslab.org/files/html5audio/">test case</a> to experience the sound issues first hand.</p> <p><a href="http://www.phoboslab.org/log/2011/03/the-state-of-html5-audio">Read complete post &raquo;</a></p> Wed, 09 Mar 2011 16:43:52 +0100 http://www.phoboslab.org/log/2011/03/the-state-of-html5-audio