In my days as an amateur magician, I noticed that as a magic-practitioner myself, I watched other magicians’ performances with a different eye than I had, when I was merely a normal spectator. I stopped being surprised or amazed when cards were discovered in unlikely places or when the shapely lady who, just moments ago, had been handcuffed, bagged, and locked inside a trunk turned up somewhere entirely different. This wasn’t particularly surprising — after all, I knew how these tricks and illusions worked. What was surprising was that now that I knew all the secrets, watching these performances became even more interesting — watching how the magician managed to get his hand into his pocket without the audience noticing, how misdirection to something noisy or shiny allowed him to set up for the next illusion in plain sight, if only anyone had been looking at him during that critical moment, etc.
Now as a game programmer, I’m noticing much the same thing. Today, I’d like to talk about levels and streaming, and the changing relationship between the two. I’m going to be focusing on console games here, but the history of PC games has been very similar. More beneath the fold.
In the beginning, there were levels. Of course, they weren’t called levels at the time; they were generally referred to as “stages”. Probably the first video game to be released with multiple stages was the original Donkey Kong, which cycled between four different level layouts. Of course, it wasn’t long before having multiple stages was a standard, expected video game feature, and every game had a “fire level” and an “ice level” and a “desert level”, to the point where it was a cliche. (Oddly enough, the currently ubiquitous sewer levels didn’t appear until much later)
The main distinguishing characteristic of a “level” is that it’s a playable space which is not contiguous with any other playable space. So for example, there is no way to travel back and forth between the “fire level” and the “ice level”, apart from having the game teleport you from one to the other. This teleport was most often part of progression within the game — you’d be teleported into the next level only when you successfully completed the previous level.
However, some games had and have much smaller “levels” than that. For example, the early Resident Evil games had each room of their mansions existing as separate levels; walk up to a door, push a button, and the game would teleport you into the next room’s “level”. Most graphic adventure games have “levels” which consist of a single screen; you’re teleported to the next room the moment you walk out of the screen.
In the early days, this was fine — data was being loaded off of a cartridge, which meant blazingly fast load times, so you could transition into the new level rather quickly. However, it began to become a problem when games started to be shipped on CD-based media, which while it can store far more data for far less money, provides much slower access to the data. As graphics improved and level data needed to become bigger, the time it took to load levels became longer and longer. Simultaneously, game designs were calling for larger and larger playable areas, which would only exacerbate the problem.
“Streaming” is based on the idea that for many types of task, you don’t need all of the data in order to start performing an operation. A classic example is playing a video file; provided that you set up the video file format properly, you can make it so that you don’t need all of the video file; you just need the part of it which is near the part that you want to play. The rest of it can still be loading from disc or over the network. As long as you’re receiving the video data at least as fast as you’re consuming it, you can start playback immediately, instead of waiting for the whole download to complete.
Inside video games, the earliest example of streaming was probably Killing Time, which could have a single “level” in memory, but also had space set aside for a “loading corridor” to be used while a level load was in progress. Loading corridors were empty corridors, usually U-shaped or S-shaped, which the player had to run through in order to travel between levels. The time it took to run through the corridor covered the time which it took for the game to load the next level. Later, this same technique was used in games such as StarFox Adventures and Metroid Prime (the latter of which also placed doors at the end of these corridors, for when the corridors were not long enough to cover the load times).
“Loading corridor” approaches were a bit fragile and not a lot of fun to program, so they weren’t used very often. Most games still used separate, disconnected levels, which required a level load when travelling between them. Some, such as Ratchet & Clank or Resident Evil 2 attempted to hide this level load by playing a cutscene over it. Sometimes this misdirection worked, sometimes it didn’t.
Now, some tech. As game graphics continued to become more intensive, and game levels continued to become larger, it was becoming impossible to contain all of a single level in memory at once; this reached crisis proportions by around 2005, and led to most commercial games moving to a “streaming” approach for their levels. However, this streaming wasn’t like the old loading corridors; this new approach allowed far more flexibility, and even allowed for modern-style “open world” games where the player has huge freedom to travel anywhere within a single giant “world” level. Here’s how it works:
Your game allocates a certain number of “level slots”. Depending on your type of game, you’ll choose a different number of slots. The fewer slots, the more data you can fit into each. The more slots, the more flexibility the system has for allowing the player to move in any direction without seeing into areas which haven’t yet loaded. An extremely linear action game might have only three or four slots. A wide-open urban game like GTA 2 might have about seven. A massive high-altitude game with huge vistas like MMORPG Tycoon might have 50 or more. Regardless of how many slots you choose to have, you divide up your levels into distinct areas, and then as the player plays the game, you load these areas into the different “level slots” as they’re required by the game. So in a linear game, if you have three slots and five areas, and the player begins in area B, you start by loading areas A, B, and C into the slots. When the player moves from area B into area C, you throw away area A, and load area D into that now-empty slot. Once the player moves into area D, you throw away area B and load area E. The same concept works for wide open games; you have a certain number of slots, and you load the nearest data into each slot, and empty the slots which contain data that the player has moved far away from, to make space for nearer data.
This system works great; it’s very simple, and provided that you can load level data faster than the player can traverse through the level, you never need to have a load screen within a level, no matter how big that level becomes. Of course, you still require a load when you travel to a new level, in order to fill up the new level’s slots for the start of the level.
As before, some games try to disguise that between-level load with cutscenes or other mechanisms to take attention away from the load which is occurring. This is how things have been for the last few years; it’s been kind of a steady state. But it’s now beginning to change again. One can look at the recently released Uncharted 2 to see what’s happening.
From this point of view, the big clever improvement that Uncharted 2 has brought to the table is that it’s not just performing its “put the nearest data in our level slots” streaming according to geographical proximity — it’s doing it according to temporal proximity. When the player nears the end of a level, it starts throwing away data from the current level and loading data for the next level, all while you’re still playing in the current level. This means that it’s able to immediately cut straight into the new level location without a load. To my knowledge, it’s the first level-based game which has managed to tie progression between levels into the traditional within-level streaming system.
You’re going to start seeing a lot more of this in coming years; in the same way that “load corridors” would make us roll our eyes today, loading sequences between levels are going to become far less accepted within the next few years. I’ll have to keep that in mind, once I start thinking about letting players look inside their dungeons, in MMORPG Tycoon. ;)