9.1 KiB
Wolf 3D
Wolfenstein 3D (shortened as Wolf3D, dubbed the "grandfather of 3D shooters") is an acclaimed and celebrated first man shooter video game created by Id Software in 1992 (released for MS DOS, as shareware), the game credited for pioneering 3D shooters and overall helping video games reach mainstream popularity. For its portrayal or violence and Nazism (albeit in the role of the enemy) the game was surrounded by numerous controversies, and still it may be yet more noteworthy for its at the time incredible raycasted graphics redered from the protagonist's point of view, featuring fully textured walls and animated sprites. At the beginning of the 90s this was deemed unprecedented realism, and it came from the hands of the brilliant programmer John Carmack. Despite the game achieving considerable success on its own, in retrospect it's remembered more and more as the first of many legendary games to come, mainly for having paved the way for its direct successor that was none other than Doom, the most influential game of all time. Wolfenstein foreshadowed the coming of a new era, it set the scene and brought us the FPS formula, even if in a rather primitive form. While yes, Doom undeniably turned out to shine as the true masterpiece, deservedly earned all the glory and stayed a timeless classic still actively play to this day, Wolfenstein became a little forgotten in this regard, being a much simpler and humble game, and yet it's the game to whom Doom owes everything.
{ Some good resources on the technical aspects of the game are the book Game Engine Black Book: Wolfenstein 3D and the ECWolf wiki at https://maniacsvault.net/ecwolf/wiki/Main_Page. ~drummyfish }
It will surprise no one that wolf 3D is proprietary, but like with other Id Software games the engine's source code at least was later on (1995) publicly released, firstly under "non-commercial use only" terms, and then allegedly under GPL, i.e. free as in freedom. Information about this is scarce and SUS, apparently Carmack one day proclaimed "yeah, consider the code GPL", and god only knows if this is legit. At any rate based on this code there was a modernized port created, called ECWolf. But it may not even matter than much as almost no one actually plays the game unironically anymore, Wolfenstein's legacy is more in its historical significance, in its influence and cultural impact.
It's fair to note that the game was neither the first shooter, nor the first game with such amazing graphics, Catacombs 3D for instance had practically the same graphics and game mechanics. Wolfenstein was ONE of the first and its legacy mainly lies in the execution of the idea, its success and influence.
The game was met with hilarious censorship as there are swastikas everywhere and one boss is literally Hitler. Germany and Nintendon't understandably couldn't allow kids to see Hitler, so they replaced everything, blood became sweat, dogs turned into mutant rats etc. That should save the poor little children souls, best if we make them think Hitler never existed. It's also funny that some guys made mods that replace the Nazis with Jews :D Quite ironic is also the fact that the Wolfenstein engine was subsequently licensed for games of completely different nature, for example Super 3D Noah's Ark, a 100% peaceful Christian game where the player throws food at animals to make them sleep.
Storyline: what? What storyline? Ah, yeah, you're basically a guy trying to escape from a castle full of Nazis, you encounter guns and hallways and you must kill everyone, there are also occasionally mutants and big guys AKA bosses. That should probably do.
Code/Engine
The game is written in C89 (with some bits in assembly) and consists of 70 files that count roughly 30000 lines of code (depending on how we count). Formatting and comments look like garbage, tabs are mixed with spaces and stuff, a bunch of empty lines suddenly appear for no reasons, inconsistencies (sometimes a function is called like f ()
, sometimes f()
), also great many ifdefs everywhere etc. Yep, there are gotos too.
System requirements were 528 KB RAM, 3 MB of disk space and 286 CPU (8 MHz).
Compared with Doom, Wolfenstein's code shows considerable shittiness, for example in that the engine isn't deterministic and literally uses floating point (although it looks like float is only used to precompute tables and that actual real time logic then uses fixed point arithmetic, but still the dependency is there). Apparently there are slips and fails such as the pseudorandom number table not containing certain values, item pickups being part of rendering code (so items can't be picked up moving backwards), or a hardcoded FPS for demos due to the fact that with variable FPS the game isn't deterministic.
Wolfenstein's rendering is arguably the most commonly examined part of the engine. It uses 1 dimensional raycasting (see also raycastlib). Textured walls, sliding door and movable walls were implemented; floors and ceilings were not textured. It goes without saying everything was rendered purely in software, GPUs as known today didn't exist yet. The levels were represented as a 2 dimensional array of cells against which rays were cast from the player's position -- every screen column would have one ray cast per rendered frame. The ray was then traced with the DDA line drawing algorithm to find intersection with the closest wall. The intersection then determined how tall the wall would appear in the corresponding screen column (based on the distance and perspective), as well as which part of the texture should be used for the column etc. Each wall texture had two versions: lighter and darker, each of which was used for different wall angles to create a primitive but effective illusion of lighting. Level geometry was naturally limited by the square grid: only 90 degree walls could be placed, there weren't any stairs, walls of different heights etc.
The game used a 256 color palette. This allowed quick fades of the screen by simply modifying the palette.
A lesser known piece of trivia is that the SNES port of Wolfenstein actually used BSP rendering instead of raycasting (source: Black Book: Doom), i.e. the technique subsequently used in Doom -- this was due to poor performance of the DDA algorithm, and the fact that BSP worked so well is actually why Carmack went on to use it in Doom.
Sprites were additionally rendered on top of the environment to represent enemies, items, decorations such as tables etc. Only sprites in the squares visited by the raycaster were drawn, from the furthest to nearest. The sprite's on-screen size was given by its distance from the player, as per perspective. The sprite was then drawn by columns and visibility was ingeniously solved by comparing the sprite's scaled height with the height of the wall in the same column (as the wall's height effective encodes its distance, so this is basically a 1D z buffer).
To quickly scale sprites and wall textures a clever optimization was used, called scalers. A scaler was essentially compiled code that would take an image and draw its scaled version without any parameters, branching or condition checking; the point is there was a scaler for every possible "stretch", so this is a kind of precomputation sacrificing memory to win speed. Precomputation is after all a theme present in the whole engine, just like in Doom -- there is a precomputed sine table, table of pseudorandom numbers etc.
AI is based on finite state machine. Enemies always occupy a single square -- when changing square the motion is interpolated to create an illusion of smooth motion. Thinking actors are represented by objtype
struct. There is one remarkably advanced feature to the AI system: sound propagation. Enemies can be awoken when they hear a noise and this takes into account separate rooms and closed/open doors. This was again made possible by a precomputed table that marks parts of the map as "acoustically connected".
Interesting places in code: ID_US_A.ASM:19
: pseudorandom number table; WL_MAIN.C:1586
: the C main function; WL_GAME.C: 1233
: game loop; WL_PLAY.C:1368
: play loop (funnily there is a hint of some kind of virtual reality support? See the variable virtualreality
); WL_DRAW.C:1336
: the raycasting function.