A New Hope
In October last year, me and Peter began having nightmares about the foundation which The Showdown Effect code was written upon. This all started when the authors of it had left the building and the one who could see through all the fog was shot in the crotch by our lead artist and we never saw him again… This gave us massive aneurisms when we began implementing hot join in The Showdown Effect.
During the gaps of rage and despair, we began thinking and discussing ways we would write our own foundation for future projects (assuming that we would still use the Bitsquid engine). We dreamt of structure and rules, nicely ordered messages, separated data and event replication, basically adopting fascism. During evenings and weekends we began hacking away, building our new hope; The Arrowhead Code Foundation.
Prelude to Foundation
A code foundation is basically (non-application specific) tools and library functions to aid development. In our case it’s loosely defined as:
“The foundation is an interface to Bitsquid, with additional library and utility functions such as GUI-toolkits. More importantly it specifies the game’s code design, architecture and communication infrastructure.”
Throughout this blog, I will describe some of our thoughts when designing and implementing this. This blog might get slightly technical, so only go on if you are sure you can see the (orthonormalized) Matrix.
Forward the Foundation – Lua and Dynamic Languages
On The Showdown Effect we use the Bitsquid engine which uses Lua as it’s scripting language. Hence, the gameplay code of The Showdown Effect is written in Lua. This was our first project we’ve done with a dynamic language and none of use had any prior experience with it. We were used to static languages with static types, which makes the syntax easier to check during compile time. In a dynamic language, less can be done at compile time and errors are instead caught in run-time (oh, the horrors). We therefore want to implement strictness and use abstract rules/guidelines. This can be achieved by designing interfaces and systems that can check if they are used correctly. In Lua we can also ‘protect‘ tables from being written to, using some metatable magic, getting read-only tables. Down the line we hope to get Lua Lint implemented in our ‘Sublime Text Bitsquid IDE‘.
The Bitsquid engine supports hot reloading of assets as well as code. This is really handy, but you have to design the code slightly different for it to work most of the time. If you initiate lots of objects/data in constructors it doesn’t matter if you reload because objects aren’t recreated. (That would be madness!) Therefore, we want to move initialization to setup functions which can be called when Lua reloads. Our class implementation supports this by calling a specific function on each object. Since our Sublime IDE can connect to the Bitsquid debugger through TCP, recompiling and reloading Lua is as easy as cake (or at least as easy as hitting ctrl+s).
Foundation – Components
We use a data driven component-based design because components are modular and easy to reuse. Data driven development also goes hand in hand with Bisquid’s design philosophy, which creates a uniform experience. We call a collection of components ‘an entity’.
Foundation and Empire – Component Dependencies and Trees
The relationship of the components within an entity can be described as a tree. For example, in an avatar entity, the root of the tree can be seen as the actual human player. The player give orders downward to control the avatar. As a child of this root, we could have the character and its state machine which define the overall behavior of the avatar. Further down the tree, we would have something like inventory, movement and so on. Basically, it is a hierarchical tree of responsibility and intelligence. A chain of commands where orders, or messages, flows from the root to the leaves.
Second Foundation – Masters and Slaves
An enemy unit might be owned and controlled by the server, but it should obviously move on all clients. We handle this by splitting each components in the enemy into a Master and a Slave part. The master calculates what should be carried out by the slave (playing effects, updating movement and so on), and then send orders / data to all slaves. If we would implement dedicated servers, the server would only have the masters. On the other hand, if we have a player as host, he/she would then have both a master and a slave.
Foundation’s Edge – Communication Infrastructure
Communication of data through network is based on delta-compressed replication, whereas events are sent through remote procedure calls (RPCs). Separating data and events gives us an opportunity when it comes to optimizing and culling network traffic. These ideas are heavily influenced by the talk I Shot You First held by Han Solo.
Internally, there are two primary ways for components to communicate. One is through ‘Messages‘ and the other is through ‘Events‘. When posting a message, it is stored in a queue and dealt with when the receiver is updated, (for cache friendliness purposes, amongst others). Messages are used as orders and can only be sent down the component tree (or via network to other units component tree). Only masters can send messages to slaves, so if you want to communicate with another component you must send it to that components master.
Events, on the other hand, are broadcasted and not used for orders. These are not stored for later, but executed immediately. Events could be “Game is Starting”, “Mission Completed” and so on. That is, important information aimed for many entities, components or other systems. Events should indicate what has been done, not what should be carried out.
Foundation and Earth – In-game Console
To debug easily an in-game console has been implemented which the game can register plugins to. This console can be opened and commands issued to the game or directly to the units selected. This can be used to tweak values, make the avatar invincible, spawn units/levels, restart missions etc. To make it easier to use, it is possible to assign hot-keys for specific commands. Most of the features of the console will be game specific though, so the foundation only facilitates the process of creating and executing plugins.
With this foundation we can hopefully deliver games with higher quality in the future.