Biolab Disaster - an HTML5 Game (plus Making-Of Video)
phoboslab.org
phoboslab.org
So, in summary, holy shit, that's absolutely amazing. Hats off.
I have two questions, though: How do you do your particle effects? Also, I noticed when you went through some code, you seemed to only point to Ogg Vorbis audio files. How does your sound system work?
(also, heh. Lesbian porn easter egg in the making-of video)
Edit: I should mention that our engine is (will be) open source. Not stealing your ideas, just really interested. ;)
Yeah, managing a "large scale" JavaScript application isn't easy. I ended up inventing a module system that loads all the dependencies before it executes a .js file's body. This is all hidden on the page, because all the files were compiled together into just one.
All the objects in the game world are derived from a base "Entity" class and inherit physics and stuff like that. So each particle, like any other object, is an Entity and not handled differently at all. When the Blob enemy dies, it just spawns some new Entities - the particles.
For the sound, the files names are all with an .ogg extension. The engine then decides if the browser can play Ogg Vorbis and substitutes the extension to .mp3 if necessary. So I _do_ have to have all sound files as .ogg _and_ .mp3. I hope that'll change in the future...
Edit: just uploaded the Editor as well. Saving is disabled, but everything else should work. Press Space to open the Entity or Tile menu (depending on which layer is currently active); hold Right Mouse Button to pan around; Z and Y are undo and redo.
So you didn't use the audio tag's <source> option? Did you find that too slow?
(also, I don't know if it'll help you at all, but I got audio working nicely on iPhone/iPod/iPad and wrote this tutorial about it http://flax.ie/how-to-get-hidden-autoplaying-audio-in-html5-...)
Edit: By the way, does your map editor output as JSON? We went through a bunch of crap getting serialisation/de-serialisation working across client/server, but you probably wouldn't hit any of those problems because your code isn't "compiled"
http://ejohn.org/blog/simple-javascript-inheritance/
I used the Audio API's canPlayType() to decide whether to use mp3 or ogg. I just found it simpler than constructing the DOM for Audio and Source elements. I'll definitely look into the sound issuse on iPhone. Thanks for your tutorial!
Yes, the levels are saved in JSON format, with a bit of boiler plate code so it can get loaded and "baked" nicely. Here's the source for the first level:
http://www.phoboslab.org/biolab/lib/biolab/levels/biolab1.js
There may be better options now.
I actually wrote a short-ass tutorial on that a while back, too. Mostly it's just JSNI, though. http://flax.ie/how-to-use-html5-audio-tag-with-gwt/#more-152
My engine code for the audio component is more or less the same as that, actually. I gave a small, quick explanation on that the other day: http://flax.ie/flax-html5-game-engine-development-diary-part...
</spam>
I found it fairly easy to do. We load the html for each sound object into the page, and then statically play/pause/stop/load them via the tag name. There's a JSON file, which contains a bunch of AudioContainer objects. When they're constructed, they construct their own HTML (so, the audio tag), and loads it into the page. Then we have a static-ish Audio service to make play/pause etc pretty easy. The JSON itself is made in our (as yet hypothetical) map editor. Must get to work on that, actually. ;)
I'm not massively happy with our solution, though. It works, but it's more complex than I feel it should be, considering that the actual implementation of it in js is so easy.
edit: I should point out that the entire point of the engine is so that you don't need Flash, which is why we're using <audio> rather than one of the pre-existing frameworks, like gwt-voices, which we would so totally use, if it didn't use Flash underneath somewhere.
Are you using http://code.google.com/p/google-web-toolkit-incubator/wiki/G... ? I'm eager for that to become part of standard GWT.
1. We didn't need 80% of the functionality that's in GWTCanvas (and canvas in general), and the 20% that we did need was a little buggy. We thought it'd simply be quicker and more efficient to build our own rather than modify or fix GWTCanvas.
2. <canvas> is, to paraphrase Tim Schafer, slower than molasses going uphill in january, on crutches. Might as well be using Flash, really. It also doesn't work on some browsers (we're unofficially, quietly, don't-tell-anyone-I-said-this, going for mobile device support as well), and doesn't work the same way across all browsers either.
What we've done is use a graphics abstraction layer, so that when the time comes that we implement it with the DOM (which we're slowly working on, but canvas will do for the moment), we need to change virtually nothing in the rest of the code.
Afaik the other half of the Flax project is writing a blog post as we speak about how we implement Canvas. I'll be sure to submit it to HN. ;)
Also, the performance is impressive. Playable without a hitch with Chrome 6 on my Eee 900.
Excellent work!
Blogpost – http://www.phoboslab.org/log/2010/09/biolab-disaster
Making Of (Video) – http://vimeo.com/14920760
That’s all linked from the game page but easy to overlook because the game is so much fun.
Kongregate looks like a fun way to try making a buck, but they only seem to support Flash and Shockwave, and I'm allergic to Adobe. :-P
<div id="noCanvas">
<p>
Hey there, it looks like you're using Microsoft's Internet Explorer. Microsoft hates the Web and doesn't support HTML5 :(
</p>
Edit: formatting.I have considered if it would be worthwhile to try putting the logic into a web worker and trigger update events to the display. Then again, sending an event from the worker to the UI thread will probably be scheduled the same way as a setTimeout event.
It's just that setTimeout seems rather slow. I have created a game with AI in Javascript, which runs fine with web workers. I tried to make it work without workers by frequently interrupting the AI thread with setTimeout events, and it was a lot slower.
It gave me a pleasant nostalgic feeling, reminding me of the Commodore 64 games I used to play as a teenager in the 1980s.
Here's hoping more of the same is coming!
Hilarious if it was intentional, and even more hilarious if it was unintentional.
Justin Bieber as the sole mp3 on the desktop is also funny for some reason, and LOLCATS/WAREZZZZ as the other folders.
Great job other than that. Judging by the code it looks like you have a game programming background.
You can enter the following in the address bar, while the game is running, though:
javascript:ig.input.bind(ig.input.UP_ARROW, 'jump');
Maybe it's better to enable it, so that Opera users would complain and it would finally get fixed (by Opera team).
You could use "keypress" event instead of "keydown" (for which for some reason preventDefault in Opera works), but this just brings other problems.
(BTW it was me who left comment about events in your blog post. For my HTML5 games, I chose to use arrows and preventDefault, as in majority of browsers it improves user experience (even in Opera problems come only when page is larger than window). Just don't forget to cancel events only for keycodes that you actually consume).
That's all I can say. You could probably make a fortune for a year or so off of the engine that drives this.
Any plans to make it work better on mobile devices?