Game Engine Development

treeback

It has never been a better time to be an indie game developer.

There are numerous intractably difficult aspects of making any kind of software. Books have been written on the subject, and continue to be. It is an open problem where no formula exists. I am not saying it is easy to be an indie game developer, but certainly this is the best time in history to be one. There are objective reasons for this:

  • Production: High quality, low-cost game engines with fantastic tools for content creation exist. A few of these engines have really only been readily available to individuals in the last few years. A few of these engines have really improved in the last few years to be usable and competitive. Commercial game engines used to be a thing exclusively for big companies.
  • Distribution: Multiple market places exist to launch a game with built in payment platforms and audiences. You can instantly reach an audience of millions if you are featured on any of these stores. As with commercial game engines, market places used to be locked down to publishers who could afford to produce physical media. Now with digital market places any dedicated individual can be competitive in the same space.
  • Promotion: With a mix of incredibly connected social platforms and well attended gaming events, there are more avenues to promotion than ever before. Long gone are the days of TV, Magazine, Radio, and Billboard advertising as the primary methods of getting a message out. You just need a strong message, good presentation, and some luck.
  • Funding: Kickstarter and Indiegogo. If you have an idea that resonates with people, and have put in a lot of effort to spread the word, the infrastructure exists to give supporters the ability to throw money at the screen and have it reach you. This means that you need to essentially self-fund the development process to the point of a demo or at least a really solid presentation, nothing in life is free.

With all of these available tools, it makes sense to leverage them. The truth is that even with this much support available, successful game projects are rare. Only 33% of game projects on Kickstarter get funded. Observing successfully funded Kickstarter video games reveals that only 37% of them deliver. The total number of started indie games vs delivered is impossible to know, many never make it to Kickstarter before being abandoned. It is safe to say that the vast majority of games started never see the light of day.

With this inherent difficulty and low success rate, it makes a lot of sense to make use of an existing game engine. If you are someone interested in starting game development, I highly recommend taking this common-sense advice. I am going to share this advice which haunts me and which has inspired this article. “Make a game, not an engine”.

This is sound advice I’ve heard directed at me before, but which I do not listen to because I am happy with my current direction. It is equal in value to the following advice which I do subscribe to. Keep your project small and well defined.

This would be a boring article if I were to just leave it at that. I’m not here to tell you what to do with your time, though I believe in sharing knowledge and making informed decisions. I have a lot of experience using Unity with C# and believe it is a fantastic tool, but Bindstone has its own C++ engine which is where I have the most fun.

Bindstone has been in development for nearly 3 years. That engine is a work in progress for the last 7 years. The oldest project I made with this engine was in October 4, 2009, you can see it here: Dark Sky Fire. The code base would be difficult to compare in size and quality, and much has been rewritten, but it goes to show how long it takes to make a commercial quality engine. I also have a strong desire to understand everything about game development even when I lean on external libraries for certain features. This is more of a personal quirk than inherent complexity.

header2

A lot of the effort required to develop a custom engine is actually in writing tools. It isn’t enough to make a wicked scene graph with a solid rendering pipeline. Having well integrated collision detection and physics is great. Having good font rendering support and UI is fantastic. Making a solid network layer is key. But none of these individual systems will flesh out a game.

It’s simple when you have a single stage game with limited assets like Tetris or Missile Commander, or if you can create a simple text format to load. Making a level, animation, and UI editor is definitely a project in and of itself. When using Unity or Unreal you immediately have an integrated editor where you can spend most of your time. For indie projects in C++ you have no such luxury, but can make use of things like Spine2D, Cocos CreatorTiled, Overlap2D. Choosing one or a combination of external pre-built editing tools will dramatically increase productivity.

Creating the Bindstone editor was a 10 month project for me with ongoing effort to this day. I leave animations up to Spine2D since skeletal rigging and animations could easily double that time. Unless you are dedicating regular full time hours you can expect a similar experience in tackling your own editor on evenings and weekends. There are only three benefits, so consider that drawback up front.

  1. You have native serialization of your types so are not beholden to maintaining a transformation layer from a general editor’s file format to your own engine.
  2. You have infinite flexibility in the features your editor supports, though the cost is that you have to develop it yourself.
  3. You really exercise your game engine by using it in more projects. Writing an editor in your engine qualifies. For me it really increased the sophistication of my UI earlier than I would have otherwise investigated it.

Tool support is an evolving landscape, when I first looked into it, I feel like the projects I linked above were not as mature. Cocos Creator and Overlap 2D both seem exciting and if I were to start again today I think I’d seriously investigate those options in addition to my existing Spine2D support.

header2

Serialization is another integral and often overlooked aspect of game engine development. Before Bindstone I had not considered this aspect seriously, but now that I have, there is no question that it needs ubiquitous bulletproof support throughout your code. Serialization is at the heart of save game formats, UI/level/game assets, configuration details, and network interaction.

Often JSON is chosen as the go-to standard for intermediate formats, there is good reason for this. It’s human readable/editable and ubiquitous. The only drawback is deserialization speed which can add up. The alternatives for save formats are often less convenient, which is a good reason not to start with something like google’s protobuf, or msgpack. But it’s a great idea to design with this in mind by selecting something other than a raw json library.

Bindstone uses cereal which has an interchangeable input/output formats. This is good because we make use of a portable binary format for real time network message parsing and for save game format JSON is fine and less fragile.

It took 2 months of evening and weekend effort to robustly integrate and debug serialization on the scene graph and component system that drives Bindstone. This was non-trivial effort which informed several bug fixes and improvements in cereal itself.

header2

Supporting multiple platforms requires a concentrated effort all the way from the beginning. Before you integrate a third party library you need to know how it will behave on all target platforms, and how to build and include it in your project. This easily bleeds into build system considerations which are abysmally boring to think about, but equally important. C++ is incredibly primitive in the area of build system and package management, Visual Studio supposedly supports native iOS and Android development now, but nobody fucking knows how with SDL.

This leaves you with either CMake, Conan, or just setting it up separate project files for each platform and maintaining them by hand. This is something I have yet to tackle that could easy be a couple hard weeks of full time effort.

All of this is pretty painless if you go with something like Unity, it has excellent one-button multi-platform build options.

This is just a taste of what people are talking about when they give you the advice to build games rather than engines. There is deep wisdom in those words. There is deep wisdom and also, deep intentional, blissful ignorance. It comes from a place of not needing to be knowledgeable about those nitty gritty details to launch a game in today’s age of game development.

header2

Ignorance is bliss, but knowledge is power.

This stuff has made me a more competent developer. There is great pride in being able to draw from full-stack engine building experience when tackling problems in game code. Plus, it’s just fun working on certain things from different perspectives.

This is a non-comprehensive list of things that I would never have been exposed to in depth without building and maintaining Bindstone’s engine. Many of these things I would have only brushed against casually if not for this exercise, any one of these I could write an article on:

  • Multithreaded particle system
  • Scene graph design and component architecture
  • Network programming from the socket layer up
  • Box2D and Spine2D integration
  • GUI implementation
  • Maintaining a 7 year old code base and keeping it modern
  • Pathfinding algorithms in detail
  • Genuine understanding of game and engine code boundaries
  • Thread pool
  • Signal/Slot implementation
  • Script integration
  • Serialization in depth

By understanding multiple aspects of engine development in depth and breadth you gain a rich appreciation for systems and interface design in code. Not just solving individual problems as they come up, but for their integration with the system as a whole. Learning to develop robust and beautiful code is an art only achieved through practice.

A game engine can be a fantastic project with which to learn and practice, there is intrinsic value for this reason alone. If you have read this far and are in the process of developing your own game engine, or are planning on it despite the time commitment trade-offs I will impart a few humble suggestions. These are not usually things you will hear, because usually people are too busy trying to dissuade and don’t get much past that.

  • Develop your game engine alongside an actual game, actually use it. Working in a vacuum for too long leads to blind-spots which are inefficient to patch up later and may result in poor decisions revealed months late.Bindstone’s engine emerged from the process of writing three small games (Dark Sky Fire, Star Collector, and an unlisted Snake clone) several years ago and refining the code base significantly. I’ve written some platformer code and gotten it to work with Box2D in an unreleased game in pretty early stages. Bindstone, of course, would make for 5 total projects, 3 which have been finished.
  • Limit the development of “speculative features”. If you don’t plan on immediately using a new feature you are developing for your engine, do not do it. I would go so far as to say, implement it in a game-specific way if you must, and then refactor and develop a clean game-agnostic interface before allowing it to propagate to too many places. You can easily find yourself well off the beaten path with no game release in sight if you don’t prioritize game-required features over wishlist items that sound fun.
  • Avoid prolific global state from the start. Singletons are not your friend (an answer/article I wrote some time ago). They are hard to remove later, and if you are developing your own engine, you really have full stack control over your architecture.

I hope this helps you in your travels. If you want to get future updates about Bindstone please subscribe!