Hacking on the game loop

I first learned how to program in TI-Basic on the TI-82 calculator my parents bought me for math camp (if that doesn’t establish nerd cred, I don’t know what does). This was back when I was in elementary school, so it was probably around 1994. The calculator came with a data link cable, and I remember exchanging games on the bus on the way to and from math camp. These were really simple games. One of them was a “racing” game, in which the “race car” was represented by a single character at the bottom of the screen and the path one had to race along was traced out by other characters heading towards the top of the screen. The game had something like 8 rows by 20 columns of display to work with, so it was pretty simplistic.

I remember how, one day, one of the older kids attending the camp showed me the Edit submenu under the Program menu. The whole world of computer science unfolded in front of me at that very instant. I was looking at the actual source code that made the racing game tick. It was foreign to me, but I wasted no time trying to figure it out. I started modifying the program immediately, piecing together a picture of the overall syntax of the language in my head based on what did and what did not cause the interpreter to whine. My first modifications were really simple, like changing the characters used for the car and the race track, making the points rack up a lot faster, or making the track narrow more slowly. I modified the game so that I could get much higher scores, which impressed the other kids on the bus — and even when they realized I was “cheating”, they were still impressed that I had modified the program.

It continued like this for many weeks, with me learning the language simply by hacking up other people’s programs. This alone demonstrates the huge benefit of open source software, something that the TI-82 was a natural platform for but more modern computing platforms unfortunately lack (imagine if kids today could immediately start hacking on all of those Flash games they play around with, for instance). I had basically taught myself TI-Basic, and since TI-Basic is a Turing-complete programming language, I had taught myself how to program, full stop. But of course my skills were still very rudimentary. Eventually I started trying to make my own games, but they just weren’t working. I hadn’t quite mastered the art of the game loop [deWiTTERS], that top-level control structure that implements the basic feedback loop of any game (get user input, change the game state, display the new state, repeat).

Cracking the game loop was actually a pretty large conceptual barrier to me. I had been writing mostly sequential code, with gotos for branching when decisions had to be made. It was messy, and the use of those gotos was preventing me from fully understanding what a loop was. I was kind-of-sort-of of implementing a loop, but it wasn’t handled consistently, and not everything always happened in the right order. I wish I had read the deWiTTERS article back then, because it would have saved me voluminous amounts of time.

Eventually I figured out the simplest form of game loop on my own, a loop that calculates the new state and then displays it with each iteration, terminating only when the game is over. That was as good as I figured out on the TI-82, because that thing was so slow even an unthrottled loop never ran too fast.

Then, in middle school, I started programming computers for real. Suddenly the hardware was a lot more capable, and the simple games I was running were executing insanely fast. I didn’t know any other way of limiting the execution speed, so I will shamefully admit that my first solution to the problem was padding out my game loops with spinning noop loops (a for statement that does nothing but eat up computation cycles). Knowing what I know now, I really wish I had seen the deWiTTERS article back then.

It wasn’t until high school, when I was writing physics simulations for graphics class, that I came upon a better way to modulate my loops. Depending on what I was doing I either coded up a constant frames per second rate (using sleep statements) or dynamically modified the dt (time step). These methods worked much better than processor spinning. I never quite reached the level of discovering the ultimate game loop from the deWiTTERS article on my own, but what I knew was good enough, and we made a pretty darn good game in college based on nothing more advanced than what I had figured out on my own.

Now, after finally having read the article on game loops that I wish I had seen a decade and a half ago, it all finally makes sense to me. Writing a game loop is a fundamental computer science skill that should be taught in the first year of computer science instruction. Not only is it fun, so the students will want to learn it; it’s incredibly useful for any real-time application. I’m quite surprised it took me these many years to finally learn about the ultimate game loop, the one that updates the game state a constant number of times per second for consistency yet updates the screen as many times per second as the display hardware will allow, using an interpolation variable to prevent spastic updates.

I’m going to go write another little physics simulation in the style of the Java applets we wrote in high school just so I can implement the ultimate form of game loop. I want to be able to say, after all these years and all these different computing platforms, that I’ve finally done it correctly. Stay tuned.

Comments are closed.