A few years ago, I was porting a game from an old Nintendo console system. The original game was written in assembler and, like many games, was a bit of a hack.
One of the effects in the game was a swarm of flies - which didn't do anything except hang around the player. Although the flies looked pretty good, I thought I could do better. So my fly simulation had simple harmonic motion, friction and a noise function, but somehow my flies didn't look nearly as cool as the originals.
Finally, I took a long look at his code. The algorithm was so short I had trouble finding it:
/* Every once in a while, randomize velocity */ if ((rand() % FREQ) == 0) fly->velocity.x = frand() * MAX_SPEED; /* Just a constant acceleration towards the origin */ if (fly->position.x < 0) fly->velocity.x += DELTA; else fly->velocity.x -= DELTA; fly->position.x += fly->velocity.x; /* ...and do the same for the other axes */
He'd found good values for FREQ, MAX_SPEED and DELTA, and volia! - convincing flies.
I've used my earlier stars code as a starting point, but changed the colors and sizes. It was so easy to make the flies do their thing that I went a little further and gave them motion blur.
Computer games normally draw a picture of the world at an instant of time. They do this at whatever frame-rate they're running at, and if this is sufficiently high, things look pretty good.
Motion blur (aka "temporal antialiasing") means doing rather more. We attempt to create an image of the world over the whole of the sampling period (16.6ms if we're running at 60Hz). The easiest way of doing this is to supersample, which in this case means drawing the world into the framebuffer more than once. In the flies example, I do 20X supersampling. The effect is quite striking: type `m' to toggle motion blur and you'll see the difference.
Pressing space pauses the flies; space again makes them single step. Press `c' to let the flies continue at full speed.
flies.c source (distributed under the terms of the GNU General Public License).
(If you want to compile it, you'll also need GLUT).
I created the four images above by slightly altering the code. With 1 fly, single buffered with clears off, you get a nice trace of its path.