Saturday, November 10, 2012

Simple cross-platform game engine - Introduction



Foreword

 This is the first one from series of planned articles on writing small and simple cross-platform game engine. In the articles I will write about topics and issues I encountered when writing our SBC Engine. As I am amateur programmer the professionals among you may find some of my solutions stupid or not effective. And it may be truth. But I am happy with our engine as it already helped us to create two games (Deadly Abyss 2, Mahjong Tris). More, the engine is still evolving and I am planning to improve it in every direction. So, your comments are welcome.

Why should I write my engine?

 Of course you do not have to. You can use any of the available engines out there. But be sure that doing it will definitely improve your coding skills as well as it will increase your object thinking. In your engine you can freely implement any features that you are missing somewhere else. You are not restricted to write everything by yourself. You can still use third party libraries like Box2D or so.

High level architecture

 Currently the engine works for Android and Windows desktop. Samsung bada is half way implemented. Why implement such a strange system like Windows desktop for mobile engine? Ok, when running it in MS Visual Studio you have very fast debugger and you can also simply share the project progress with other team members that may not own real Android device. But it has other features. For example if you, in development phase, let assets unpacked your grafician can replace them simply in assets directory and see how it looks in game.

 Here is how the engine is structured:
 On the very bottom is sitting real system you are running the game on. Every system has different APIs and different behavior so you have to unify it somehow.

 This unification takes place in box labeled System. There are specific claeses for each supported system (vertical boxes with system names). These classes are converting the calls into so called services that appears to the rest of the engine identical regardless of the actual system. For example there is TimeService that is responsible for timing the game loop, measure how much time elapsed from last tick and so on. This class also can return current ticks in milliseconds when getTickCount() is called. On some systems it only passes the query to the underlying system and returns the result while on others it may do some calculations with system returned values. From engine point of view all this is hidden and when programming new engine features you just call getTickCount() and you are not interested more how the result is created. The relation between these system classes and real OS is one-way. You know about the system but the system does not know anything about your classes. It sounds natural in this level but may not be so obvious in creating further, higher level, parts of the engine. This one way relation is also applied on Engine -> System relation and Game -> Engine and Game -> System relation. It allows you to write new game without changing engine and also it allows you to develop new features in the engine without changing System layer.

 Beside the system specific services you can also see other classes in the System layer. These classes are here to define very basic types like Point, Rectangle, Vector, Dimension, ... Point, Vector, Dimension are all just typedefs for the same. Giving it different names helps to maintain code readability (I am sitting on the "chair" not on the piece of "furniture" while both is right). The arrow pointing to underlying system is dotted as some of these classes may encapsulate something from system while others not. For example the Math is there to create unified access to math functions across systems while Vector is independent template class. Because of this system dependent / independent mixture I left all these classes in System layer instead of implementing it in Engine layer. Beside this I expect Engine layer to provide one step higher operations than just define Rectangle or any other basic class.

 Engine layer then defines operations above system, basic classes like batching sprites for renderer, managing assets, managing texture regions, handling game lifecycle, ... Here any ideas about what your engine should be capable of can be implemented. Of course, there are lot of times when for some feature you will have to open the System layer and adjust it. But it does not violates the rule that System does know nothing about Engine. For example if you want to add some camera features into engine you will have to create camera service in System layer.

 On the top of you engine that consists of System and Engine layer you then build your games. If the engine has all the features you need for actual game you are working on then your role is "game programmer" and your previous role "engine programmer" can be forgotten until game programmer asks engine programmer to implement new feature.