Very few games can escape the need for an Entity framework. An Entity framework defines the core pieces of interactivity for your game. Over the years, I have implemented and reimplemented Entity frameworks dozens of times. In the interests of easing the development process and providing stable libraries on which to rapidly build games (rather than simply create technology), I introduce the following Entity framework that will become the foundation of more advanced topics in game engine development.
What is an Entity?
An Entity simply describes a managed, usually interactable, object within your game simulation. In asteroids, the player’s ship, his missiles and each individual asteroid would be an Entity. In a Bejeweled clone, each of the gems might be an Entity. A particle effect might be an Entity. The World boundaries in an Arena shooter might be an Entity. People will have different preferences for what should or should not be tossed into the Entity framework, based on their different needs. Generally speaking, though, if you can shoot it, pick it up, bump it, or if it moves, it’s probably a good candidate for an Entity.
From a technical point of view, the Entity is typically the glue that brings all your subsystems together. It usually will integrate graphics, sound, collision detection, AI and game logic. An Entity is a “thing” that you can play with.
What belongs in an Entity framework?
Depending on your particular implementation, your Entity framework can be a simple object management system, or it can be the center piece of all interactions within your game simulation.
Generally speaking, we want to develop code that is bug-resistant, easy to maintain and reusable. While it might be tempting (and sometimes convenient) to move domain-specific logic into the Entity framework, I prefer to have a core modular system which I can extend for the needs of a particular game.
Basic Entity Framework Functionality
When deciding what belonged in the Entity framework, I came up with the following minimal requirements for basic functionality.
The Entity framework should hold on to my Entity references and keep them safe from garbage collection.
The Entity framework should handle frame-safe addition and removal of Entities. If you don’t know why this is necessary, consider yourself lucky. These sorts of bugs can be brutal.
The Entity framework should give me a convenient mechanism for safely referencing other Entities without having an actual reference. In other languages this would be handled more cleanly with weak references, but we can accomplish similar functionality with IDs and a look up function. The true usefulness won’t be apparent until we get deeper into the engine design, but the important thing to remember is that we can’t serialize references, but we can serialize IDs. Serializing forms a critical component of load/save systems and networked games so we’re going to lay the foundation as we proceed.
The Entity framework should provide you with a convenient way to clean up Entities at the end of the game. There are certainly other ways to do this, but enforcing “dispose” functionality here lets us be a little more lazy in our game-specific implementation.
Otherwise, stay the hell out of my way.
Components of the serenity Entity framework
Based on our minimal requirements, I made the following decisions:
The Entity must be an interface, not a base class. Implementers need to be able to have their Entities inherit from a DisplayObject, a NetworkedObject, a SaveableObject or whatever other system they may desire. There is no reason not to make Entities an interface.
We don’t care who assigns the ID, just that an Entity gets one. For that reason the framework comes with a simple ID counter that can be used, or the implementer can provide his own. The Entity interface requires only that the Entity provide some sort of globally unique ID. IDs are also implemented as strings rather than ints in order to provide maximum flexibility to our implementer and the subsystems he is trying to tie together.
To facilitate simple clean up, we will require our Entity to define “dispose” functionality.
The last Entity requirement is that it define a “tick( a_deltaTime : Number )” function. If your game is frame based, delta time is 1. Delta Time is in seconds (Number) or milliseconds (int) depending on your preference. This is the part of the design that I struggled with the most. The tick functionality on an Entity isn’t strictly necessary. Ultimately I decided to include it because the convenience of having it in place outweighed any engine design choices it appeared to be making on your behalf (if you don’t want to use it, just implement an empty function instead).
The meat of the implementation is within the EntityContainer class. The public functionality for EntityContainer looks something like this:
addEntity( a_entity : Entity );
removeEntity( a_entity : Entity );
tick( a_deltaTime : Number ) : void;
dispose() : void;
getEntityAt() : Entity;
numEntities() : int;
lookupEntity( a_id : String ) : Entity;
The functionality should look strikingly similar to that of the built in DisplayObjectContainer. That’s because, to some extent, they are performing some similar functionality. This is dictated by our Coding Conventions.
Using the serenity Entity framework
To effectively use the framework, then, you need to create a class that implements the IEntity interface. Instantiate and hold on to a reference of an EntityContainer and feed it entities as they are created and remove them as they are no longer relevant just as you would DisplayObjects with a DisplayObjectContainer. Call the EntityContainer’s tick function once per tick, to signal each Entity’s tick, and to process the add and removes for that tick. That’s pretty much it.
To add functionality to the Entity framework, there are two ways to do it:
Do it somewhere else. The numEntities and getEntityAt functions on the EntityContainer means you can keep the logic of the query separate from the management responsibilities of the EntityContainer. This is the preferred method as it supports the Single Responsibility Principle.
Subclass the EntityContainer and add the functionality that you need to your new subclass.
Source code is included with a simple example showing an implementation of the Entity class. The example just does some pretty spiralish action based on the Y position of the mouse.
[…] over at gamepoetry.com just posted an article about Entity Frameworks for Games. From the article: Very few games can escape the need for an Entity framework. An Entity […]