This is part 4.1 of the multipart Trap Labs Code and Architechture Series.
Why write a game engine? Most indie developers making small games are perfectly fine lumping on chunks after chunks of code onto their game until it’s no longer worth maintaining, then it’s time to move on to a different project, right? If you are considering writing a game engine it usually means you want reuseability and extensibility for your game. Reusability is a given, but I want to specificially focus on the extensibility part.
Now when I talk about extensibility I mean extensibility with focus. It’s generally not realstic nor possible for your game engine to be infinitely extensible, because otherwise you’ve just invented general AI, and you should be using it to enslave the world and not reading my articles. When I talk about extensibility of any software it’s about the extensibility within its own domain. That is, the game engine should be extensible within the confines and requirements of your game. For example, a car racing game engine might focus on extensibility in terms of part customization, adding new tracks, new cars, and vehicle dynamics. An ARPG might focus on extensibility of skills, equipment customization, NPC interactions, and quests. A low level game engine like Cocos2d-x or Unity is meant to allow you to extend low level features such audio, visual, and physics to build your own game.
Game engines can cover multiple domains like how Unity is multi-domain. What’s important is that your domains are (somewhat) clear. If you want to make a RTS game like StarCraft, then it’s probably unwise for you to think “hey maybe I can make this into an FPS as well because that’s never been done…”. Unless the value proposition of your RTS game is to play like an FPS, don’t go about designing code that interferes with the game’s core focus.
For Trap Labs it was clear to me that the game engine should easily be able to extend the following:
Since Trap Labs is based off modular maps and being able to plug and play components at will, it was vital that all of the above could be developed as extensions to the core engine. Ideally, a good game engine should remain untouched when adding new features. However, this is not always possible. As you’ll see that it’s not realistic nor practical to completely lock down the engine interface. Things like the event system will often drive the design in strange ways. This is why writing unit tests for your engine is very crucial to verify correctness such that it’s resistant to defects during an upgrade or modification. This is also why you need to decouple your engine from any framework you that you are using.
Originally I wrote this article as a standalone part, but during process I realized it was too big to cover in a single article. So I decided to split it up into multiple subparts.
If you are going to write an engine it will probably look vastly different from mine because of requirement differences. However, the underlying code design and architecture principles are similar so hopefully you’ll be able to transfer that knowledge to your own game.