Erik's blog

http://twitter.com/#!/erikjmoller

Subscribe to RSS feed

SVG is awesome, but not the tools

,



I've been working on a WebGL tutorial movie on my spare time and I wanted to make a slide to show some bits of the OpenGL timeline that are relevant for WebGL. I tried a few options, but ended up doing it in SVG. Both diagram and background. Personally I still think the tools out there are a bit awkward to use. My normal work flow is quickly hashing it out in svg-edit then grabbing the source and hand editing it until it's the way I want it. Check out the background svg... soopah neat. That's so much nicer than slapping a jpeg in the background. 1,078 bytes uncompressed.

<?xml version="1.0"?>

<svg viewBox="0 0 2880 1800" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="none">
	<defs>
		<style>
			circle {
				fill: black;
				stroke-width: 1;
				stroke: #111;
			}
		</style>
		<pattern id="pat" patternUnits="userSpaceOnUse" viewBox="0 0 16 16" width="27" height="27">
			<circle cx="8" cy="8" r="4"/>
			<circle cx="16" cy="16" r="4"/>
			<circle cx="0" cy="0" r="4"/>
			<circle cx="0" cy="16" r="4"/>
			<circle cx="16" cy="0" r="4"/>
		</pattern>
		<radialGradient id="grad" gradientUnits="userSpaceOnUse" gradientTransform="rotate(-40) translate(0, 1700) scale(2,1)" cx="0" cy="0" r="1000" fx="0" fy="0">
			<stop offset="0%" stop-color="#555"/>
			<stop offset="20%" stop-color="#444"/>
			<stop offset="40%" stop-color="#333"/>
			<stop offset="100%" stop-color="#111"/>
		</radialGradient>
	</defs>
	<rect fill="url(#grad)" x="0" y="0" width="2880" height="1800"/>
	<rect fill="url(#pat)" x="0" y="0" width="2880" height="1800"/>
</svg>


The actual slide is an html with an inlined svg. Another 2,165 bytes making the whole slide land somewhere just over the 3k mark.

<!doctype html>
<html>
	<style>
		html,body,svg {
			width: 100%;
			height: 100%;
		}
		svg {
			display: block;
		}
		body {
			margin: 0px;
			background-image: url("background-industrial.svg");
			background-size: cover;
		}
		circle,path {
			stroke: white;
			stroke-width: 5;
			fill-opacity: 0;
		}
		text {
			fill: white;
			stroke-width: 0;
			font-size: 80px;
			font-family: tahoma;
		}
	</style>
	<body>
		<svg viewBox="0 -400 3050 200" xmlns="http://www.w3.org/2000/svg" xml:space="preserve">

			<title>OpenGL timeline</title>

			<text x="1000" y="-800" style="font-size:150px">OpenGL timeline</text>

			<g>
				<title>Developed by SGI, direct mode, fixed function pipeline.</title>
				<circle r="10" cx="300"/>
				<text x="200" y="100">1992</text>
				<text transform="translate(350,-50) rotate(-60)" >OpenGL 1.0</text>
			</g>

			<g>
				<title>Successive improvements like multitexturing, cubemaps, VBO.</title>
				<circle r="10" cx="500" style="stroke:gray"/>
				<text style="fill:gray" transform="translate(550,-50) rotate(-60)" >OpenGL 1.X</text>
			</g>

			<g>
				<title>Programmable pipeline, GLSL</title>
				<circle r="10" cx="1000"/>
				<text x="900" y="100">2004</text>
				<text transform="translate(1050,-50) rotate(-60)" >OpenGL 2.0</text>
			</g>

			<g>
				<title>Programmable pipeline, OpenGL ES SL</title>
				<circle r="10" cx="1600"/>
				<text x="1500" y="100">2007</text>
				<text transform="translate(1650,-50) rotate(-60)" >OpenGL ES 2.0</text>
			</g>

			<g>
				<title>Direct mode and fixed function dropped</title>
				<circle r="10" cx="2000" style="stroke:gray"/>
				<text x="1900" y="100" style="fill:gray">2009</text>
				<text style="fill:gray" transform="translate(2050,-50) rotate(-60)" >OpenGL 3.1</text>
			</g>

			<g>
				<title>OpenGL ES 2.0 for the web</title>
				<circle r="10" cx="2400"/>
				<text x="2300" y="100">2011</text>
				<text transform="translate(2450,-50) rotate(-60)" >WebGL 1.0</text>
			</g>

			<path d="m50,0 l600,0 l50,50 l50,-100 l50,50 L2850,0 M2950,0 l-100,25 l0,-50 l100,25" />
		</svg>
	</body>
</html>


I'm no html/svg-wizkid so I'm sure there are a couple of improvements that could be made, like removing the preserveAspectRatio=none which is hiding a bug in 11.60, and removing the overflow:hidden which is the typical sweep-under-the-carpet-fix and really figure out why I get a v-scrollbar, but all in all I always get struck by how elegant and simple it gets when you do some svg stuff. It's a shame it's lacking in the tools area or I think it would be used so much more!

EDIT: So @erikdahlstrom (co-chair of W3C SVG WG and fellow Opera-gfx) came to the rescue on my scrollbar carpet sweeping note. As it turns out the svg element is an inline element and that in some way which is clearly beyond my box model skills causes a few extra pixels to be added to the body element. The solution is to either set the line-height to 0 for the body element or to do what I did which I think is the neater option:
svg {
	display: block;
}

Fostering a programmer

,

This might be a tad on the personal side for this blog as I'm normally only writing about work things, but I felt obliged to follow up on my last post.

This Sunday morning (no church goers here I'm afraid) I decided to see if I could expose my daughter to the wonderful world of BASIC.

I certainly didn't want to force her so without saying anything I lifted down the TV on the living room floor, went upstairs and literally dusted off the C64, took it downstairs, hooked it up and tuned in the right channel.

Annika, recently awoken, immediately looked up from behind her coloring book and asked "What's that? What are you doing?". I said "This is my old computer that I had when I was your age. I'm going to try it out again.". She frowned and said "That's a computer? It looks more like a keyboard!" as she sat down next to me on the carpet.

[ It's at times like these you realize that you're from a different era than your kids... Like the first time Annika wanted to watch a movie at grandma's place. Grandma gave her a VHS cassette. Annika tried to pry it open but couldn't so she eventually turned to me asking "Dad, where's the disc?"

Or like on another visit to grandma when she asked me "Why is grandma's phone tied to the wall?" ]

For about an hour we played around with the old C64, starting with 1 PRINT "ANNIKA"; 2 GOTO 1, the infinite loop printing ANNIKA all over the screen, testing her math skills by using stuff like PRINT(7+5) and finally we sat down with the old game book and entered in "Death valley" together.

She played it a few times, going through the whole spectrum of emotions from "Boohoo it's too hard!", via proud smirk as she beat it the first time and all the way to "Sigh...is that all?" as she beat it the third time.

Was she bitten by the programming bug? No, I don't think so, but none the less I think it was a good experience and I'm not giving up that easily.

I think when I grew up, before the time of Internet there weren't as much digital entertainment readily available so I kept coming back to my book of BASIC games and eventually learned to make my own. Perhaps the fact that the difference between a commercial game and one you typed in yourself wasn't as great back then as it is now made it more inspiring to make your own games.

Why would kids of today be entertained for long by 50 line ASCII games when there's an abundance of polished and art directed games available for free? And why would they make their own games when whatever they come up with will look like crap when put next to any $1 game on the app store?

I still have hope though. I think a Raspberry PI with two motors hooked up provides some appeal no flash game can combat. I will persevere. Even if my kids end up as hairdressers or construction workers I will make sure they have at least been given a better than average chance to pursue a career in computer science.

Let me get back to you in 10 years when she's decided what university to attend!

I'm teaching my kids to code this weekend! - are you?

, ,

Raspberry PI has been getting a lot of press recently and I'm following the project with great interest. I really admire the people running the project...it's such a good cause.
Just the other day I was flicking through a photo album mom had recently given me... you know the old fashion type with physical pages to turn and photos made of paper and I came across this image.

It's me hacking away on my Commodore 64 back home in the kitchen. The C64 is hooked up to a black and white TV and you can tell it's easter from the coloured feather decorations mom always put in the windows around that time of the year.

The picture was dated as well and I started counting backwards and realized I was six years old. And really, that was nothing exceptional back then. In the early 80's most kids had a home computer. I was perhaps introduced slightly earlier than some since dad was a programmer at IBM and bought a Sinclair ZX81 for me and my brothers when I was just four.

Back in the 80's you could buy these books which contained small BASIC games, about a page or two long each, nicely illustrated and explaining the bits and pieces that made up the game. I owe a lot to one of those books.It was a book in Swedish (I presume it was translated from an English original) full of space games and it was titled plainly "SPACE GAMES for VIC, PET, SPECTRUM, ZX81, BBC, TRS-80 and APPLE".

One of the best things about it (though I didn't think so at the time) was that the games were riddled with typos, which of course meant that you couldn't just copy the source listing, you had to try to understand what it did to make it run!
The book also did an excellent job with explaining all the instructions like LET, GOTO, GOSUB etc plainly and often posted little problems for you to solve like "How would you make the valley longer?".
I guess it's slightly ironic the second instruction EVERYONE learned back then is the now often despised GOTO. The first one was PRINT and that was all you needed to be entertained for hours smile

One of my favourites was "Death Valley" where you steered an asterisk which was supposed to symbolize your "Single seated speed dart" space ship down a narrow valley which was simply made up of capital i's. You can see a "screenshot" on the front of the book, except they've "touched it up" by making it in color...it was all monochrome!

I guess there's no surprise I ended up working for a long time in the games industry.

So.. what's the point of all this nostalgia? Well, I realized my daughter who is now 7 years old is a full year older than what I was in that picture coding in BASIC.

She being a girl (sorry guys it's just a fact that girls are more mature for their age) should be ready to start her path down computer science lane!

Perhaps we who grew up back then were fortunate in that games weren't as readily available as they are now? Would my daughter have the patience to copy a 40 line code listing to play an ASCII game, or would she throw it aside, go get her iPhone or Chromebook (yes I know I work at Opera, but I got it for free) and fire up one of the thousands facebook-, flash- or html5-games available for free? Who knows... but I'll damn well try this weekend!

Imagine the advantage for future math studies of grasping what a variable is at age 7...or an equation...or just knowing that ArcTan is something you use to figure out angles with. How could I deny my kids that head start.

I'm dusting off the C64, and as soon as they're available I'll be buying a Raspberry PI board each for the kids (and one or two for myself). And we're going to solder our Gert boards together and hook up a motor and some LEDs to it. I'm sure my kids have skills I didn't have when I was their age, like pinch-zooming and emailing, but I'll be damned if I don't give them the same opportunity to learn programming like my parents did!

You have kids? What are you waiting for!

requestAnimationFrame for smart(er) animating

,

Quite a while back Paul Irish wrote a good blog post entitled "requestAnimationFrame for smart animating" where he introduced the new API and also presented a shim that you could start using that would be future proof. Implementations are now catching up with the shim, but there are still a few lacking it and considering the longevity of old IE versions there will be for quite some time. It didn't take long until I realized the shim is easily (mis)used causing it to drift.

A simple example. Let's say you are using requestAnimFrame (the shim) to drive an animation that you're expecting to run at 60FPS. That gives you 16.7ms to draw each frame and looking at the shim that's exactly the timeout set if it's not implemented in the browser (1000 / 60). If you call that at the start of your frame and then do your rendering that's fine. But what happens if you by chance call requestAnimFrame AFTER you've done your rendering? Say for example that you're using up 15ms to render each frame. Then when it's time to draw a frame you'd first render for 15ms and then wait for 16.7ms before drawing the next frame. Each frame would then take 31.7ms and you'd only be able to get an FPS of 31 as compared to 60 if it's natively implemented.

I've seen this one time too many to let it slip. I should've done this the first time I was asked to check out some sample running slower in Opera, but procrastination is for cool kids.

EDIT: Thanks to Joel Fillmore for spotting that the time parameter to the callback was missing. While editing this I figured I might as well update it to include the cancelRequestAnimationFrame. I'm yet to see it used in a real world sample, but for completeness.

(function() {
    var lastTime = 0;
    var vendors = ['ms', 'moz', 'webkit', 'o'];
    for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
        window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
        window.cancelRequestAnimationFrame = window[vendors[x]+
          'CancelRequestAnimationFrame'];
    }

    if (!window.requestAnimationFrame)
        window.requestAnimationFrame = function(callback, element) {
            var currTime = new Date().getTime();
            var timeToCall = Math.max(0, 16 - (currTime - lastTime));
            var id = window.setTimeout(function() { callback(currTime + timeToCall); }, 
              timeToCall);
            lastTime = currTime + timeToCall;
            return id;
        };

    if (!window.cancelAnimationFrame)
        window.cancelAnimationFrame = function(id) {
            clearTimeout(id);
        };
}())


It's certainly a little bit wordier than the original shim, and perhaps a bit trickier to read, but it does its best effort to account for drift and you can call it wherever you want in your update loop.

The built in timer is of course never quite high rez enough when you do stuff like this, not to mention what it's like when you're running it on battery power on a laptop, but that's a whole different story.

All hail iOS 5

, , ,

I'm not going to bash Apple so don't worry if you're a fanboi, you can read on...I have at least 7 Apple devices at home that are frequently used.

iOS 5 is here, there is much rejoicing in the streets! While I followed flowery prose comments on twitter about how blazingly fast everyones HTML5 got with this update I was silently muttering words a family father will have to just mutter instead of saying out loud. My neat little iOS game Emberwind had gone from running perfectly smooth on any prior iOS version to a stuttering sluggish mess on iOS 5.
The first choice for a programmer is of course always to blame the OS or gfx-driver or keyboard or whatever seems remotely plausible before scrutinizing your own code... to be perfectly honest it did seem reasonable to do so this time... I hadn't changed a thing and it went from 30 FPS to 10-ish FPS.
I think I muttered more than once "POS iOS 5.. don't they do any automated regression testing on their releases at Apple!?!".

I don't know the answer to that question... I'd be interested to hear, but I'm guessing not or they would've spotted this and let people know.

I'm not going to ramble too much, let's dive into the solution... precision!

Yes, you heard right... precision, you know the little precision qualifiers everyone who's starting out with some WebGL or GLSL copies from a sample, that little seemingly insignificant
precision highp float;
Cause let's face it...everyone always picks highp!
What it does is to determine how much precision the GPU should use for your floats and ints etc. At least 2^-8 for lowp, 2^-10 for mediump and 2^-16 for highp when we're talking floats.

So how did this affect Emberwind? Well, it's a 2d game so you're mostly only moving textured clip space quads so there really is no need to use anything but lowp (EDIT: Re-read my post when it was mentioned on the WebGL mailing list and I actually meant to say mediump here). Or at least that's what I thought I was doing... turns out there was one place, in the vertex shader where I hadn't specified precision. The GLES Shading Language spec clearly says


The vertex language has the following predeclared globally scoped default precision statements:
precision highp float;
precision highp int;
precision lowp sampler2D;
precision lowp samplerCube;

The fragment language has the following predeclared globally scoped default precision statements:
precision mediump int;
precision lowp sampler2D;
precision lowp samplerCube;




Which meant I really were using highp in the vertex shader. Now the regression in iOS 5 appears to be that using a highp varying in the vertex shader will promote any mismatched varying in the fragment shader to highp thereby causing a major performance hit. You can see a profile run of the game using highp struggling to reach 13-14 FPS. (Note how lovely quiet it is on the CPU except when loading)


Using lowp in the second sample it sits quite comfortably at 33 FPS. It's a quite staggering difference. And if you say "You call 30FPS smooth?" Then my only defence is... well...it's a port...they're always second class citizens! You're so damn tired of the game by the time you get to ports so you're bound to take a few shortcuts. 30 FPS seemed like a reasonable one.

So, summing up... dropping from 33 to 13 fps because of precision! It may not matter much on desktop graphics hardware, but it apparently very much does on mobile... that goes for you WebGL-ers as well... not just native app devs!

Now I just need to send my one line optimization off to Chillingo and get it all fixed on the appstore!

And finally.. I'm speaking at New Game Conference in SF together with heaps of other talented speakers. It'll be awesome... and you should come! Free Chromebooks for everyone if they sell out 97% of the tickets!

Emberwind and what's next

, , ,

Hi again, it's time for a long overdue update on Emberwind. As usual, real life (tm) happens in waves and after Siggraph I was swept away by a big one and I'm up late again trying to catch up on things. My list of things I'd like to do which I always have scribbled down in my trusty old-school notepad just keeps getting longer and longer. In fact, in the process of pushing the latest update to the Emberwind github pages I wrote another item down on my list. I noted that the resource JSON file for Emberwind is quite wordy, taking up about 1.7MB and just removing all the whitespace shrinks it down to 700k. So, I did a quick google search for a JSON minifier. I found one by Crockford and a few others. I ran them all and looked with disappointment on my 7 idle cores while processing the file. One of them, written in Python allowed me to kick it off, go take a long shower and come back only to find it still working with the file. Rightfully it got a swift Ctrl-C followed by a Shift-Del to make sure it didn't linger in the trashcan.

So, the item added to my notepad was "Write C multicore enabled JSON minifier". I haven't yet figured out how I'll manage that, the gut feeling was to partition the file in X bits, search for the first recognizable JSON construct (or potential JSON construct) and process the segments in parallel. I think the only certain JSON construct you can find when starting at a random location are the escaped characters in a string, like
\" \\ \/ \b \f \n \r \t \uXXXX
That may be a bit limiting though so I guess you could also gamble on things like { and [ but that means you will have to throw away the results if it doesn't line up (i.e. is inside a string).

Well anyways, it'll be an interesting task. If there's already one out there that I don't know of please let me know. And should you beat me to it then that's great... the todo list is growing a bit too long in any instance.

Anyways, there's quite a large update to Emberwind with heaps of new game objects. Tutorial cards that should explain the controls etc. It runs great. The internal build of Opera I tested it in today runs at close to 120 fps. Not bad at all.

So what's next for Emberwind? Well I don't expect I'll be adding much more gameplay to it, but I do plan on turning it into a full fledged canvas performance test. What I want to do is to get rid of whatever javascript overhead there is in the demo by adding another render device implementation to it that just records all the draw-calls in a long array and dumps that to a file. I'll then write a really simple little js-app that reads the array and executes the draw-calls as quickly as it can, much like the Quake demo's. It'll be a great tool to use to profile and optimize Opera with.

I'm also hopefully going to go to Austin next year to hold a talk about Emberwind and html5 game making at SXSW. Please take a moment and go check out my suggestion and give it a thumbs up if you'd like to see me there.



I'm going to be at the New Game Conference in San Francisco on November 2nd to do a talk on Emberwind (1pm). I'm really looking forward to that. There are a lot of great speakers there, Ken Russel (WebGL WG Chair) and Ben Vanik (author of WebGL Inspector) from google are going to be there to do a talk I'm really looking forward to, and of course EA sending Richard Hilleman is a great boost for making people take html5 as a game development platform seriously. There are many, many more great speakers, so if you have the time, go check it out!

I'll probably also be at the HTML5 party in Madrid... not entirely sure what the topic is for that talk yet, but we'll see smile

I think that's it for now. Don't hang around here, go make html5 games!

A new home for Emberwind

, , ,

Here I am again writing up a blog post close to midnight. Too many things I'd like to do, too little time...
Today has been a hectic day indeed. I started the day by trying to get my slides for Siggraph in order and of course today is also launch day for the original Emberwind on the AppStore so I've been pretty busy chatting to reviewers and following up on emails. Go check out the new neat page at Chillingo. It's really rewarding to see reviews, comments and feedback from gamers start pouring in. That's what makes it all worthwhile!


We haven't been idle on the html5 front either. Today we're premiering the new home for Emberwind html5 at github. Github has some pretty neat features, one of them is "pages", meaning you can also run the latest Emberwind snapshot directly from github! Be sure to bookmark that page!

This time you'll see that even more game play has made it into the snapshot. There's all kinds of different loot to pick up, houses to enter and light the fireplace in, doors to crack open, splashy water to knock those feisty little gremlins into, more gui elements and of course your trusty white snow owl Wick to take you around the stages.

There's been quite a number of optimizations going in this time as well which really shows in how smooth it runs.

It is really starting to shape up and become a neat game. A shout-out goes to the summer interns that have done an awesome job with the port. Marcus, Ingemar and Alex, it's been loads of fun, I hope you've enjoyed it as well!

Time to whoop some gremlin ass

, , , ...

It's time for another development snapshot of our Emberwind HTML5 port. There has been heaps of features going into the game since last time. The trigger system that just missed the mark in the last snapshot was pretty vital in getting a lot of these features in. With that in place we've been able to add ladders to climb, gremlins to smack about and caves to explore. Getting the in-game sound and music going as well really helps with the game feel.

I'm actually going to praise Apple for iOS 5 a bit later in the post so let me just even that out right here and now. Safari on Windows and

Canvas performance

, , ,

One of the things you have to decide early on when you make a 2d game (or for the UI for a 3d game for that matter) is what resolution and aspect ratio you want your game to run in. Aspect is perhaps the most important thing as you can often get away with scaling assets. When I did Emberwind I decided we wanted to have both 4:3 and 16:9 aspect ratio and therefore the original assets were made in both 800x600 pixels which is 4:3 and 1066x600 pixels which is 16:9.

There are of course other ways to go about this, but this approach was simple; internally the game always rendered at either 800x600 or the slightly wider 1066x600 and scaled up if required (of course more recently the game was ported to iOS and we added 15:10 to the list).

Now, when making Emberwind for html5 you obviously want it to be able to run at a wide variety of screen resolutions and you resize your screen using the technique described on html5rocks. The question though is "What do you do when you render at a different resolution than the one the assets were created for?". One of the guys working on the Emberwind html5 port asked if his approach was right, he would never change the internal canvas size and let the element be scaled (and hence linearly interpolated). It certainly makes sense for window sizes larger than the internal 800x600. There's little point in using a larger canvas than the source assets. But what about when you're scaling down? Instinctively I replied to his email saying "When scaling down you want to set the canvas size so it maps one to one and scale the individual draw-calls. It's not going to matter for hardware accelerated builds, but for anything running in software it's going to be all about fill-rate so you want to keep the backing resolution as small as possible."

The minute I sent that email I thought to myself "Dammit... you know better than to make claims about performance without data to back it up!" So here I am, coding up a test case and writing a blog post well past midnight after having put the kids (and Mrs) to bed.

It is as I expected, at least almost. My first test case is rendering 1000 alpha blended buttons into a canvas that is 480x320 (iPhone3) large on-screen but is using the 800x600 backing. On my laptop I get about 9 frames per second in Opera Next and 0 frames per second on my iPhone3 in Safari (which are both software canvases at the moment). Testcase number two is doing the exact same thing except the backing canvas is 480x320 (i.e 1:1 to screen). On my laptop I'm getting 23 frames per second and on my iPhone3 I'm getting 3 frames per second. It's not very surprising as one is pushing about 3 times as many pixels only to finally scale the end result down.
Safari on the laptop shows similar results to Opera.
In Firefox on my laptop, running a hardware accelerated canvas you get the expected result of about 50 frames per second for both versions. Chrome quite surprisingly runs at 100 frames per second with the 800x600 backing but drops to 43 frames per second when using the 1:1 canvas. Perfect test-case for you Google guys to fix... though you'll have to file the bug yourselves! IE clocks in at an impressive 140 frames per second.

One last thing before I go to bed, when writing this I noticed our favourite browsers perform their interpolation a bit differently. You can try the testcase yourself. Here's a 2x2 checkerboard canvas scaled up to 200x200.

Opera
Firefox Chrome Safari IE9

Emberwind HTML5 - sweep circles and line soups.

, , , ...

Sweep circles and line soups... huh? Well, it has to do with collision and as an old game dev it's just a bit amusing doing this in two dimensions rather than in three. What I've been accustomed to work with are sweep spheres and polygon soups. "Sweep sphere" is a term meaning the elongated shape a sphere sweeps out as it moves forward, and "polygon soup" just means it's a bunch of polygons without any sort of implied relationship or organization.
The collision and movement system that you are going to see in action today has been used in several shipped games on several platforms in various incarnations and when I did Emberwind I stripped it of one dimension and made some additional simplifications (so in fact it's no longer a line soup, it's all lines making up convex shapes). Ingemar has now ported the collision and movement code to js and the net result is that you can move the main character, Kindle the gnome, around the levels.

The latest Emberwind HTML5 development snapshot has been tested on Win7,OS X,Ubuntu and iOS with the latest versions of Opera, IE, Firefox, Chrome and Safari (where available), but that doesn't actually mean it's gone through proper QA, so apologies if it doesn't work on your specific configuration. If you do run into an issue please take the time to give us a description in a comment.

There are about 11Mb of data to download the first time you run it so we did have to put some progressbars in there.

Movement is of course not the only new feature of this snapshot, heaps of work has gone into making it more like a game experience with splash screens and menu buttons. There's also the neat feature of run-time selection of the renderer backend. If your browser supports WebGL it'll default to run that which will be visualized by a yellow button in the top left corner with a WebGL icon. Pressing that button wil toggle the renderers between regular 2d canvas and WebGL, hopefully really seamlessly and swiftly. If your browser doesn't support WebGL it'll show a grayed out button showing the 2d icon and nothing will happen if you try to press it.

This snapshot also makes use of the excellent Google webfonts to render text into the game. Kudos to Google for that one!

Alas the trigger system just missed the cut-off for this snapshot (so you can't use the ladders or entrances), but that gives us something to show you next time as well. For this snapshot we've expanded the testing quite a bit and we'll continue doing so over the next couple of weeks hoping to get it to run on some devices where you normally wouldn't expect this kind of HTML5 content. We'll also be tidying up the Audio system and getting that integrated into the demo, adding in some game objects to interact with (read: to bitch slap) and also looking at some optimizations to reduce the number of draw calls.

It's been an interesting week, looking forward to giving you the next update.