Musings on Game Engine Design

An Anatomy of Despair: Introduction

without comments

I’ve been working for a little more than three years on the Despair Engine, the game engine that Day 1 is using in Fracture and another, as-yet-unannounced, title.  In the beginning, there were two of us working on the technology, me and my longtime friend and collaborator Adrian Stone.  Now we’ve got thirty programmers working in the same codebase.  Fracture’s getting close to shipping.  This seems like a good time to look back at the principles that shaped our initial architecture and at the decisions whose consequences we’re living with today.

The name started as a joke.  Adrian and I were out to lunch with our lead one day.  Somebody made a crack about naming the engine “Despair.”  One thing led to another, and by the end of the meal we’d plotted out a whole suite of despair-themed content creation tools, most of which never got made.  It was 2004.  We were starting from scratch on core technology for big-budget AAA games running on consoles that didn’t even exist yet.  We figured that “Despair” would work one way or the other, either as an imperative to our competitors if we succeeded or as a sadly accurate description of our own feelings if we failed.

There are two broad opposing ideologies when it comes to engine design for games.

Call the first the Low-Level Faction.  This school of design traces its roots to embedded devices and to early consoles like the Dreamcast and the first PlayStation.  This school is characterized by a preference for coding close to the metal, tends to produce games rather than game engines, and eschews abstraction in favor of raw performance.  Many of the games produced by this school of thought are raw C rather than C++, or if they are C++, they tend to minimize use of C++ features like polymorphism, virtual functions and templates.  When Insomniac’s Mike Action says at GDC that “Software is not a platform!  Hardware is a platform!” he’s voicing this faction’s frustrations.

Call the other group the Abstraction Faction.  This school of game engine development grew out of PC game development, where audio, graphics and I/O devices are hidden behind a driver layer.  Programming straight to the hardware simply isn’t an option.  The programmers of this school learned their trade on a platform with virtual memory and highly variable capabilities, so they learned to use levels of indirection to abstract away platform differences.  When the Epic guys say they’d sacrifice 10% of their runtime performance for a 50% improvement in content creation time, they’re justifying their higher level of abstraction.

Both ideologies of engine development have produced great games.  Halo, for example, is a straight-C game of the Low-Level Faction.  Gears of War is an example of a game with a lot of abstraction that uses lots of script and the advanced features of C++.

The lesson that I’ve learned in a decade of software development is that the specific decisions you make are less important than that decisions are made at all.  Software requires structure.  Every decision has tradeoffs, but once made, even seemingly-arbitrary decisions have to be enforced, or entropy will consume your codebase with a vengeance.  Every-man-for-himself design will get you a million lines of code, any one of which may reference any other, and any one of which may have undefined side effects.

The Despair Engine is an unapologetic representative of the Abstraction Faction of game engine design.  This is not because I think that’s the only way to create games.  It’s because that’s the way that I know how to create games.  We use the advanced features of C++ very aggressively.  If our history of uncovering compiler errors is any indication, the Despair Engine is unique among game engines in the degree to which it pushes the infrequently-explored edges of the language.  We use STL containers and algorithms.  We use the Boost library of C++ template extensions.  We use template metaprogramming to create our own embedded domain-specific reflection language.  And we use abstraction and polymorphism throughout our code.

Over the coming weeks, I’d like to discuss some of the Despair’s more unusual idioms and axioms.  For each, I’ll describe the problem that our approach was intended to solve, and I’ll talk about the continuing challenges of the solution that we implemented.

Written by Kyle

April 15th, 2008 at 10:15 pm