Friday, January 11, 2013

Rocks! Update #2 - it's a game

It's an actual game now!

So, first things first - here's the current version of Rocks!


New features include:

  • updated graphics - random rock shapes, and a progression of sizes
  • on-screen instructions
  • better sounds
  • proper collision detection
  • particle effects when things are destroyed
  • more than one level
  • a "shield" that will prevent rocks from running into you

It's looking a lot more like a real game now.

Sound design is hard

Oddly enough, the hardest thing for me so far has been making those decidedly "retro", simple sound effects. The Web Audio API is very powerful, but it's also very much focused on doing sophisticated manipulation of sampled sound. I certainly could have grabbed appropriate sampled sounds, or built some in Audacity, but I wanted to push the "classic" feel of the thing, and I thought - "I've done this sort of thing before, how hard can it be"? Besides, attaching a couple of huge sample files to a game that's currently under 20kb total in size felt a bit like the tail wagging the dog.

Of course, the last time I tried to create synthesized sounds from scratch was probably 30 years ago, on an 8-bit home computer with a fixed-voice synthesizer chip. There's something to be said for the existence of fewer choices helping to focus your efforts. When you're faced with an API that supports multi-channel surround sound, arbitrary frequency- and time-domain manipulation, 3-D positional audio, dynamics compression, and all the rest, it's a little difficult to figure out how to just make a simple "beep".

Here's what I've learned so far about using the Web Audio API:

Web Audio is based on a connected graph of nodes, leading from one or more sources through the graph to the ultimate audio output
This is enormously-flexible, and each of the individual node types is jut about as simple as it can be to do the thing it's designed for. There's a "gain" node that just multiplies the input by a constant and feeds it to the output, for instance. The source nodes don't have individual volume controls (because there's the gain node for that).

There's one weird quirk to my old-school sensibilities, which is that every note requires making another source node and connecting it to the node graph. When a note stops playing, the source node is automatically removed and garbage collected. If you want to play the same sound over and over, you're continuously creating and destroying nodes and connecting them to the graph.

There's a simple oscillator source node that's very flexible
You can easily create an oscillator that uses an arbitrary waveform (square, triangle, sine, on user-defined), plays at a specific frequency, and starts and stops at a specific time. This is about 80% of what you need to make a "beep", but:

Oddly, there's no built-in ADSR envelope support
Back in the day, we'd set up ADSR (attack, decay, sustain, release) parameters for a sound, which would control how quickly it came up to full volume, how loud it was as the note progressed, and how quickly it faded. There are probably about 10 different ways to do the same thing in Web Audio, but nothing with the same simplicity.

There's no simple white-noise source
This is a bit of a weird omission, in that noise sources are the basic building blocks of a lot of useful effects, including explosions, hissing, and roaring noises. And again, there's probably 10 different ways to solve this with the existing building blocks, each with their own limitations and quirks. I ended up using Javascript to create a buffer of random samples, which I could then feed through filters to get the appropriate noises for thrust and explosions.

The API is very much a work in progress
Despite the fact I wasn't trying to anything particularly sophisticated, I ran into a few bugs in both Safari and Chrome. I imagine a certain amount of this is to be expected with an in-development API that hasn't been standardized yet.

Next Up: Enemies!

The next big feature for Rocks! is to have some enemies to chase you around and shoot at you.


UnwiredBen said...

I'm getting a lot of canvas warnings in Firefox/Firebug when I try this out. They don't seem to affect game play, but might be slowing things down.

I've also seen an occasional hiccup during gameplay, I'm assuming is some kind of GC. The whole reason I brought up Firebug was to see if there was some object leak happening.

Mark Bessey said...

Hmm. It appears that Firefox doesn't like setting the style attributes to "undefined". Easy enough to fix, I'd think.

A few hundred log messages a second will definitely affect performance...

Burraco said...

Thank you for your great post. This blog is great.

Rummy said...

Loved this post. Thanks for sharing your day!