I recently wrote a game, and found it very much like developing a Javascript-based web application. (My wife, who's a journalist with the video game industry beat, insists "it's a toy, not a game. There is a difference." I will defer.)
If you're a web developer who does a lot of Ajax, there is one kind of event in which you're often very interested. Most events describe what just happened, but advanced Ajax and DOM coding often rely more on what just stopped happening. The Image.onload() and the XHR (XMLHTTPRequest) objects' onreadystatechange handlers are interesting because they tell us when something that takes time is done, not when something has begun.
Another, related component of javascript development is setTimeout(). setTimeout is basically on(when clock reaches this point)=somefunc(). It's not worded that way, but eventually you'll wrap your mind around that basic idea. setTimeout() is just another way of shoving something into the list of events. Along with all the objects on the screen, each of which might have one or more events associated with it, there's a general object, the clock, to which you hook up events with setTimeout(). When you understand this, you'll realize the basic truth:
Everything in web application development is event-driven. Everything. The same is true of games.
The gametoy I wrote is Thinksaber, which is basically a re-implementation of MacSaber for Linux-based Thinkpads. It's written in python and the core is pretty straightforward:
idle_channel.play(sounds['idle'][0])
while 1:
event = pygame.event.wait()
if event.type == idle_channel.get_endevent():
idle_channel.play(sounds['idle'][0])
if event.type == pygame.JOYAXISMOTION:
self.make_noise()
This is a very stripped-down version of the actual core, but it's all we need to understand the main point. Lightsabers, when not being swung around, make an ambient menacing hum. I reserved a channel in the pygame sound interface for that, and call play() on it when the gametoy starts up. (Actually, there's a chunk of code in the actual program that also plays the startup sound, too.)
That sound clip is only so long. When it stops, it has to be restarted. That's what this loop does: if the event was a sudden motion of the laptop, call the make_noise method to figure out how fast and in what direction, but if the event was "end of idle sound," restart the idle sound.
I was struck by just how similar this is to monitoring onload, onreadystatechange, and setTimeout. You, the programmer, don't actually have to do the monitoring; these events are delivered to you on an as-needed basis. The only major difference between game programming and web programming is that in game programming, at least using the PyGame interface (and many others that I've seen), the loop and the dispatcher are explicit. They're only two lines long, but once you know they're there, you start to see their presence under the hood of IE and Firefox.