An alternative to adhoc game coding?
Did you ever wonder what a games engine is, or what they do or why they are important? In this article I try to write about my own experience developing general purpose games engines.
I have been working in the games industry for several years. I started as a developer for educational software and games and ended up being a games engine coder. The first engine we made was a 2D engine. We built one because we needed it. We were a content provider at the time and one of the customers wanted to use their own inhouse "games engine" and produce a fairly simple educational game. That engine really sucked. It was merely a buggy pure C graphics library ported from DOS to Windows. One needed to code even the animation render loops over and over again. And they were proud of it. Hehe. They would not allow us to build a game from scratch. So, we sat down and asked ourselves what to do. First we added a layer that encapsulated their library and all of the OS functionality. We even encapsulated main(). Then we needed to get rid of the render loops. So, we invented a game class, a level class, a sprite class, an animator class (in fact the base class of the previous mentioned classes) and several other classes to deal with sound, resources, controls, etc. These classes were called the game engine. The engine was purely event driven. Events could come from device objects, standard objects and game objects. In less than a few weeks we were up and running and completed the project without much delay. What we had lost by developing the run-time system and games engine we had gained by coding the contents.
Our engine was very limited, but the advantage was that after we were finished we could replace the run-time system for one that worked better without changing a single line in the code of the games engine and the game itself. That worked. The design worked well. During the years the run-time system and games engine grew and a lot of titles were produced with it. A bit off topic: One of the developers (a Linux fan) hated the Windows, but was glad that he didn't have to deal with it. All of DirectX and Windows were hidden.
In everything we coded for the game we asked a simple question. Can this be generalized in a reusable class? This caused me to write a run-time system and games engine of 450,000 lines in about 3 years. It became a full time job.
When we finished our last project (a real-time riot game), times changed and required a 3D engine. What to do? Because 3D is very different we couldn't reuse a lot of the 2D code.
One could build classes which hide the details of D3D and any other low level sub-systems, like 3D Sound, multi-media, input devices and the operating system API. One could also create classes for things like object, resource, scene and thread management. Also one can add a class library for common things like strings, BSP trees, octrees and the like, shaders and special effects. Manager classes were designed that allowed subscription to services. These classes are much like an abstraction layer. We called this layer a run-time system.
On top of that one can produce a true games engine. That layer encapsulates input events from the devices, 3D graphical objects, 3D sound, object messages, AI, etc. It also encapsulates common objects in games. One can have classes for walls, floors, ceilings, doors, weapons, projectiles, light sources, explosions, water, non-player characters, player characters and interface objects like buttons, gauges, etc. One could have specialized objects that are able to walk, fly, speak, etc. There would be a singleton for the entire game, classes that manage levels, areas, scenes, etc. So, this layer hides the technology and focuses on the game contents.
Such an engine comes at a price. First it needs to be developed. That takes a long time and one cannot focus developing on such a dream engine for years. We need to make money right? On the other hand, engines will allow to reduce developing cost, because games can be developed faster, will be easier to maintain and will be more reliable. We seriously looked at commercial games engines and advanced ones had a 6 or 7 figure price tag. We also looked at open source engines. None of these two types did what we expected of a games engine. Even the expensive Quake engine looks like a graphics library. So, we decided to make our own. We were given the time to make a rough working skeleton with only the functionality required for the next game. First target was the demo. Mad as we were we even developed the engine in our spare time. And when we were required to start production of the actual game time was scheduled for the engine. Yes, it was risky, but we believed in the long term advantages and we have seen the advantages of our first one before.
The game is coded solely using the games engine. And for features that are not implemented already one would use the run-time system. In the game code one is not allowed to include any Windows or DX headers. If one requires these then the run-time system needs to be expanded or there is something seriously wrong with the design.
What are those advantages? Developement cost can be reduced because coders are busy with the contents and not with the complex technology. That is a very important aspect. Also, if the underlying technology changes then only the run-time system needs to be changed. The engine itself and thus the game will not have to be changed. Does that happen often. Hehe. Well, DX 9 is here and another one is in the works and when you are nearing completion no doubt MS has a new flavor of Windows. You could also think about porting to other operating systems or consoles.
One could argue that having these 3 layers (run-time system, games engine and game) will produce an overhead. This appears not to be the case, because in C++ we have the help of class templates, inline member functions, inline assembler and macros. Because of their global scope I am not a fan of macro functions. Afterall, these layers should not be the performance bottleneck itself.
Sometimes people think that an engine limits the games it can produce. That is true for game specific engines. The Quake engine relies on BSP trees for an example. That limits game levels to be indoor only. An outdoor setting is likely to use octrees for an example. Other engines are too specific and limit themselves to a given game type (first person shooter, advanture, strategic game, etc.). What most engine designers forget is that games have a lot of common tasks. If you specialize in that then the engine is usefull in more situations. Such engines are uncommon. So, it is a matter of how you design it.
Not only building the engine itself requires time, but one also needs tools, like level editors and BSP tree builders. Again you need to ask yourself if a given tool built for a specific game can be designed to be reusable.
Too bad we were not able to finish it. The company was not able to fund itself for the next project. I still have some code hanging around on my hard disk and when I look at it then I wished we were able to finish it.