Enginuity, Part I
engine #39 you' games going game it' code
Have you played Valve Software's Half Life? It's one of my favorite games. The gameplay itself is the standard for the genre (first person shooter), but the atmosphere and style of the game - the dirty, lonely bowels of the facility; the wonderful little scripted sequences (like when the scientist gets killed by the tentacle monster in Blast Pit - I love that part); the times you're left cowering in a corner, hiding from the marines and aliens engaged in a massive firefight. If it were a book, it would be un-put-downable; I came to realize this when I noticed I was chasing the Gonarch through the tunnels of Xen with my RPG, growling.
No? Perhaps, then, you like the related games, Opposing Forces or Blueshift? Guiding lost marine Adrian Shepherd past even nastier monsters than Freeman encountered, but with an enhanced arsenal at your disposal to help you out. Or taking on another day on the job as security guard Barney Calhoun, risking life and limb to get those scientists out safely (although those who *have* played it know that the scientists always meet with.. unexplained accidents, hmm?).
Prefer multiplayer? Counter-Strike is an absolute phenomenon in the online gaming world - it's one of (if not the) most popular online games worldwide. Terrorist versus Counter-terrorist in games of hostage rescue, sabotage, assassination... or more recently, I've heard of a game called Natural Selection, which manages to combine elements of Real-Time Strategy games with the popular team deathmatch.
OK, enough advertising (I take cash only, guys). All these games have a major thing in common. In each game, around 50% of the code is exactly the same as the others.
No, really. If you strip out all the 'content' - not just the maps and models, but the AI, physics, and 'gameplay' - you'll be left with pretty much the same thing in each case. A system for rendering small, urban environments, with a skeletal animation system, a bunch of special effects, networking, input, and sound. And that, ladies and gentlemen, is Valve's Half-Life engine.
Think about what I'm saying here, for a moment - Half-Life and Counterstrike are, beneath the differing models and weapons, essentially the same program. As are They Hunger and Sven Co-op, Todesangst and Day of Defeat.. a fairly large amount of diversity stemming from a single code base, a single engine
Now, apply that to your own projects. If you had a reusable engine like that, most games would just become a question of creating new maps and models (or the equivalent for your projects); menial tasks like initializing DirectX or OpenGL and reading in settings from storage would become a thing of the past, as you'd just use the code you wrote previously.
I hate to break it to you, but all that knowledge of the Win32 API you've built up probably won't be very useful in the industry; as more and more companies lean towards the professional 'software factory' technique, they'd need to you write the Windows portion of an engine once, and after that you'd be useless. Many projects never touch underlying APIs - they use an engine to do it for them, either bought in or developed in-house. Valve, originally, bought the Quake source code to turn into the Half-Life engine - as a result they never had to touch things like OpenGL, because iD Software's code did it all for them. They just knuckled down and integrated their specific game content (AI, physics, etc) into Quake's engine interfaces. (Well, ok, so they actually *did* go in and modify the engine to support more advanced features like 16-bit textures, but my point is that they didn't *have* to).
So, in this series of articles, I'm going to do my level best to teach you how to build an engine, from scratch. I'm not just going to present you with code and say 'call function X to do funky things;' by the end of this series, you're not just going to have an engine - you're going to understand it. So listen up, maggot! :-P
It's important to realize that in practical terms, an engine can't do *everything* - the more things the engine has to support, the more low-level it becomes, until you're just writing a wrapper for DirectX/OpenGL. No, when you write an engine, you have to lay down some rules about what games can build on it - you can't build Doom 3 on the Half-Life engine, for example, because Doom 3 requires some things (like per-pixel lighting) that the Half-Life engine simply doesn't provide. More obviously, you couldn't use the HL engine if you were planning a game for GameCube, because HL doesn't support the platform.
However, it's my belief that this process of 'specialization' happens step-by-step - an engine starts, at it's lowest level, supporting every possible game, and then as you add more to it, it 'converges' on a set of limitations. You can picture it as a pyramid - the base is wide and supports the rest, while the top is a finely focused point, allowing only a very small set of games to be built on top. If we remove the top half of the pyramid, we're left with a much wider base to build a larger set of games on - those games will, however, need to do more of the building work themselves. So an engine can be progressively built up in this way, adding layer by layer.
Development requires a certain level of Enginuity
This series of mine is going, layer by layer, to take you through building an engine - as you may have guessed, I'm christening it 'Enginuity' (shoot me when I'm done writing).
Here's the 'requirements' for the engine:
- It has to be as cross-platform as possible (That is, 'desktop' platforms, not consoles - Windows 98+, Linux, and Mac OS X).
- It should be reusable.
- It should support cross-platform networking (that is, games on Linux can network with games on Windows, and so on).
- It should be designed in such a way that it's simple to add new components or replace existing ones on a project-by-project basis.
- It should run at adequate speeds on a Pentium 3 1.1ghz machine with 32mb GeForce 2 graphics card (that's our 'minimum spec,' or 'minimum technical requirements,' more or less. Much of the speed will depend on the game you run it with, though - a 3D shooter will obviously run slower than Tetris, even though they may be built on the same engine).
- It should be designed in a way that is fairly simple to understand and teach (otherwise I might just as well be talking to myself here
Feel happy - you can tell people that you're going to 'achieve reusability through modularity in an object-oriented design.' (Not that you couldn't tell people that before, of course. Unless you had your mouth full or something. My point is.. actually, never mind).
No series of articles would ever be complete without source code, and rest assured that it will be provided in ample quantities. In fact, the source may cover even more than what I talk about - you'll get to see things that I toyed with before deciding not to discuss - like the bits left over from my attempt to build the engine as a DLL under Windows, and other (usually fairly irrelevant) things that may serve to confirm your fears that I don't know what the heck I'm talking about.
I cannot stress enough that an engine is a large, fairly complex topic, and newbies should not even think about approaching it until they're totally competent with the language (C++). Put it this way: If you can work out what a 'templated class that inherits from multiple virtual base classes and overloads the pointer-to-member operator' is, then you're ready. If not, then sorry, but you simply won't understand some of the code and design techniques I'm going to use in the series. You're welcome to glean what you can, but I'm not going to pitch to the lowest level here; if I spend all my time explaining language concepts, we won't get anything done.
What's the ultimate aim of this, then? I'm thinking that building a game engine isn't nearly as much fun unless you build a game on top as well (because, let's face it, general-purpose game engines are what you make when you're out of ideas for games). So what I'll try to do is, at opportune times, build simple games (we're talking *really* simple) on the engine in it's state at the time. You can almost think of them as milestones in the development process.
That's about all I've got to say for this article. Next week, I'll give you an overview the 'foundation layer' of the engine, and cover some of the most fundamental topics, such as error logging and memory management. In the meantime, you'll want to be reading up and downloading SDKs from the following places:
http://www.libsdl.org/ - Home of both SDL and SDLNet (SDLNet in the Libraries section).
http://www.fmod.org/ - The FMOD home page.
http://nehe.gamedev.net/ - The (in)famous NeHe OpenGL tutorials (newbie to pro in sixty minutes, or something like that)
Richard Fine (rfine at tbrf dot net)