Game Entities and Representing Objects in a Game

This is the 2nd article in the series Building a Game Structure. Be sure to read the introduction and article 1 which discusses building a foundation for your games.

I’m going to discuss how different objects should be represented in your games and do my best to explain the idea behind my reasoning. I’ll provide the code I am using for my entities, and explain that a bit as well. So let’s get started. First of all, I feel that it is best to categorize your game objects into two categories: Entities and Game Objects. Let’s talk about Entities first.

What is an Entity?

An entity can represent any physical object in your gameworld. Entities are generally things that can be interacted with in some way, or just anything that holds a position in the world. This could include: A barrel, door, powerup, player, enemy, trigger area, wall, etc.

All entities will use the update/dispose interface. Entities may contain other entities and game objects in a hierarchical structure as well. They contain the basic data to represent themselves in game space such as position, rotation, size, scale. Each has a unique ID associated with it for debug and storage purposes.

Ideally Entities will replace the need for multiple class types for each different enemy by providing somewhat of a “template.” In order to provide more functionality we do things such as extend the basic Entity class with “MovingEntity” which provides movement data, and in a later article I’ll discuss a “Vehicle” class which provides AI to the entity. Each individual game will extend those basic classes further with a general “Unit” class that can provide more specialized data such as health, damage, etc.

To make the Entity classes as reusable as possible we will provide basic hook functions that can be used or overrided by subclasses. We want to make it as easy as possible to centralize the creation of these entities within a factory class, and even create a way that these can be built using external data. Rather than having a long list of constructor parameters, we create an “EntityParameters” class that holds the basic startup variables to be passed through to each entity on creation. This will make it very easy to do the things we just discussed.

Why Use Entities?

One question some may ask is why we create a class to represent our objects rather than simply extending MovieClip. Well, the answer is that it is quite inflexible to extend MovieClip because you may wish to represent your object with several different types of graphical data. This approach I am preaching is more along the Model View Controller design pattern, which allows for the greatest of expandability. Also, there are some things that make using entities extremely faster than dealing with Display Objects directly.

What is a game object?

Now that we are clear on what an Entity is, and the idea behind it…isn’t that what a game object is? Well, yes and no. A game object can be any of the following: A Sprite which graphically represents an entity, an AI routine which must be calculated each frame, any sort of game GUI such as menus etc. A game object’s definition is really quite broad, but we will consider anything to be a game object which needs to be updated and disposed of properly and does not have an actual “Game World” representation. I suppose that leaves the question of…

What is the “Game World”?

The Game World is simply the area in which the entities reside. What would be displayed to the screen can be considered as what is visible in the “camera.” The Game World is in fact an entity itself. I don’t want to go into any more detail on this right now, because it will be discussed in detail with another article.

Let’s build our Entity

Note: This version of the Entity class has a small bit of it’s final functionality taken out. What you see below is the core of it, however we will build upon it slightly in future articles to allow for greater usefulness within our greater game structure.

I’m going to list out the interface of the Entities and Game Objects. I’ve commented the interface here. To see the full code you may download the files from the google project page.

This is used for anything that will be considered a Game Object

public interface IGameObject extends IEventDispatcher
{
	function update( timePassed:int ):void;
	function dispose():void;
}

These are for the construction of our entities.

public class EntityParams
{
	public var parent:Entity;
	public var radius:Number;
	public var id:String;
	public var rotation:Number;
	public var scale:Number;
 
	public function EntityParams()
}
public class MovingEntityParams extends EntityParams
{
	public var maxSpeed:Number;
	public var doesRotMatchHeading:Boolean;
	public var boundsBehavior:String;
        public var friction:Number;
	public function MovingEntityParams()
}

The basic Entity class which can represent any stationary object.

public class Entity extends EventDispatcher
 {
 	public function get scale():Number
 	public function set scale( a_value:Number ):void
 	public function get id():String
 	public function get parent():Entity
 	public function set parent( a_value:Entity ) : void	
 
 	/**
 	 * NOTES: The following variables are left open rather than using getter/setters because they are accessed
 	 * 	often and thus this VASTLY improves performance.
 	 *
 	 * 	newPos and actualPos ( have to use these since we don't do getter/setter )
 	 * 	newPos var should be what you change if you wish to change pos externally.
 	 */
 	public var newPos:Vector2D;
 	public var actualPos:Vector2D;
 	public var rotation:Number;
 	public var radius:Number;
 	public var bounds:AABBox; 	
 
 	/**
 	 * ID's are assigned automatically. If it is necessary to force an ID then set it
 	 * in the parameter file passed through the constructor.
 	 *
 	 */
 	public function Entity( a_params:EntityParams )	
 
        // The basic interface
 	public function update( a_timePassed:int ):void
 
        public function dispose():void
 
        // Each entity may inherit the basic hit detection functions or create it's own specialized version.
 	public function isOverlapping( a_entity:Entity ):Boolean
 
 	public function isOverlappingCircle( a_pos:Vector2D, a_radius:Number ) : Boolean 	
 
        // The following is the interface for handling child entities and game objects
 	public function addChild( a_entity:Entity ):void
 
 	public function removeChild( a_id:String ):void
 
 	public function clearChildren() : void
 
 	public function getChildByID( a_id:String ):Entity
 
 	public function getChildren() : Array
 
 	public function addGameObject( a_gameObject:IGameObject ):void
 
 	public function removeGameObject( a_object:IGameObject ):void
 
 	override public function toString():String
 
  	// -- PRIVATE --
 
        // These are hook functions to be used or overrided by subclasses. They are used within the update function.
  	protected function updateChildren( timePassed:Number ):void
 
  	protected function setInitialValues( timePassed:int ):void
 
  	protected var _stepSize:Number;
        protected var _parent:Entity;
 
 }

Now our Moving Entity which handles any movement data. Keep in mind that the movement logic used by this Class may be changed slightly depending on the game you are creating. Things such as rotation speed constraints etc may be applied, however this is a basic moving entity example.

public class MovingEntity extends Entity
{
	public static const BOUNDS_BOUNCE:String = "bounce";
	public static const BOUNDS_WRAP:String = "wrap";
	public static const BOUNDS_REMOVE:String = "remove";
	public static const BOUNDS_NONE:String = "none";
 
        public function get friction() : Number { return _friction; }
	public function set friction( a_value:Number ) : void { _friction = a_value; }
 
	/** CAUTION!
	 * The heading variable is left open for speed purposes, however it should only be set externally
	 * using the setHeading function! The side variable should never be set externally.
	 */
	public var heading:Vector2D;
	public var side:Vector2D;
	public function setHeading( a_value:Vector2D ):void		
 
	public var speed:Number;
  	public var maxSpeed:Number;
  	public var boundsBehavior:String;
  	public var doesRotMatchHeading:Boolean;
 
	public function MovingEntity( a_params:MovingEntityParams )
 
        // a simple way to get the entity to face a target position.
	public function rotateToPosition( a_target:Vector2D ) : void
 
        // apply a one time force to the entity. It will be removed after it is calculated.
	public function applyForce( a_force:Vector2D ) : void
 
        // add a constant force such as gravity to the entity.
	public function addConstantForce( a_force:Vector2D, a_id:String ) : void
 
	public function removeForce( a_id:String ) : void
 
 	public override function update( a_timePassed:int ) : void
 
 	override public function dispose() : void
 
 	// -- PRIVATE --
 
        // Some new hooks are added
 	override protected function setInitialValues( a_timePassed:int ):void 	
 
 	protected function calculateForces():void
 
        protected function calculateFinalVelocity():void
 
        protected function updatePosition():void
 
 	protected function updateHeading():void 	
 
 	protected function wrapOnBounds():void
 
 	protected function bounceOnBounds():void
 
 	protected function removeOnBounds():void
 
 	protected var _forces:Array;
 	protected var _constantForces:Dictionary;
 	protected var _newVel:Vector2D;
 	protected var _velocity:Vector2D;
        protected var _friction:Number;
}

Wrapping Up

We now have a way to easily represent entities and thier associated objects in our games. The next steps would be to to create a class to manage all of our objects and entities effectively, as well as a generalized graphical representation class for our entities. Then we will want to centralize creation of entities and objects to a factory class, and ideally support external data driven creation.

In the next article, we will discuss game object management and we will create some renderers for our entities. For now, be sure to check out the example code on the google project page.

1 Star2 Stars3 Stars4 Stars5 Stars (4 votes, average: 5.00 out of 5)
Loading ... Loading ...

8 Comments so far »

  1. poze nunti said

    am January 2 2009 @ 6:14 am

    Funny blue ball..
    I might need some help in the future, are you available for some work ?

  2. Colby Cheeze said

    am January 2 2009 @ 6:21 am

    If you have questions, send them my way.

  3. Iain said

    am January 29 2009 @ 8:33 am

    How do you get around the fact that an object might be, say, both a “moving object” with speed and position and a “killable object” with health and armour, without having one extend the other, so that they can be used separately? Just an example of course, in practice you’d never really want something killable that can’t move. Flash doesn’t have multiple inheritance, so I’ve thought about making a “movable” behaviour object that is owned by an entity and is responsible for the entity’s position, and a “killable” behaviour object that controls health etc. Any thoughts?

  4. Colby Cheeze said

    am January 29 2009 @ 9:48 am

    Well, if you are creating some sort of unit that will have health and other properties…and will need the behaviors of the MovingEntity then you simply extend the MovingEntity. So here is a short example of a Unit that might be used in an adventure or RPG type game, ( and btw, I’ll be getting around to a post about this stuff soon in any case. )

    public class Unit extends MovingEntity
    {
    public var maxHealth:Number;
    public var health:Number;
    public var maxMana:Number;
    public var mana:Number;
    public var attackPower:Number;

    public function Unit( a_params:UnitParams ) : void
    {
    health = maxHealth = a_params.maxHealth;
    _mana = maxMana = a_params.maxMana;
    attackPower = a_params.attackPower;
    m_armorType = a_params.armorType;
    m_armorTable = a_params.armorTable;
    }
    public function doDamage( a_value:Number ) : void
    {
    health -= a_value * m_armorTable[ armorType ];
    }

    private var m_armorType:String;
    private var m_armorTable:Dictionary;
    }

    So now you can use the health properties etc of Unit, and still do the movement of it such as unit.x += SOME_NUMBER;

  5. Nick Wiggill said

    am February 11 2009 @ 11:22 am

    Iain,

    Very good question. In response:

    1. “Favour composition over inheritance.”
    2. “Build to interfaces, not implementations.”

    1. We make use of the “Single Responsibility Principle”: A class (and thus it’s instances) has one and only one responsibility. So you create a class Collidable that deals solely with collision detection, and you create a class Living that contains functionality solely pertinent to measuring life remaining. Now you create a third class which is the Entity, and at runtime it instantiates Collidable and Living, and holds references to them. It calls them at the appropriate times to deal with the appropriate logic. So you can see that we are *composing* the object, rather than deriving it’s functionality through inheritance.

    2. Interfaces describe the *services which a class provides*, rather than how you implement those services. So say you have two different methods of collision detection. One is for objects moving along a straight path, and one is for objects moving along a sinusoid.
    So, let’s say you implement an interface ICollidable (from which your class Collidable will extend) which accurately describes the services a “collision-detectable object” would expose, eg. “checkMyCollisionWith(someOtherObject)”. You can now split your Collidable implementation into two: One that manages collisions for object which need only simple collision detection, and another for objects which require more advanced collision detection (eg. for concave polygons).

    This is useful because it means that, at runtime, you can dynamically decide how to compose your object… rather than using inheritance, because inheritance leads to an inflexible hierarchy, as you have realised. This is particularly true in ActionScript, because multiple inheritance is not supported. So you can use the same skeleton, Entity, for all your entities, but you can dynamically decide how to create each individual one according to it’s type, eg. player, AI-controlled, static objects, etc.

    DISCLAIMER: The Gang of Four (Gamma, Helm, Johnson, Vlissides) claimed that one should always “Favour composition over inheritance”, but this is not quite true, and they later admitted as much. There are many cases (this article is a perfect example) where it is 100% the best way to go. But in many cases, inheritance is a lot more logical. Example: I’ve recently built a pseudo-3D rendering engine. At each step down the inheritance chain I have extended the functionality a little bit more. So I start out with an abstract renderer, I extend it to a 2d (flat) renderer, and then extend it further to my pseudo3D (perspective-based) renderer. This works because there is no branching of the inheritance chain — just three different classes, each of which does a little more than it’s parent class.

    Best regards,

    -Nick

  6. Nick Wiggill said

    am February 11 2009 @ 11:27 am

    Hmm, incomplete edit on that last post, where I said:

    “So say you have two different methods of collision detection. One is for objects moving along a straight path, and one is for objects moving along a sinusoid.”

    …I had meant to say:

    “So say you have two different methods of collision detection. One is for circular objects, and one is for concave polygon objects.”

  7. Visual Harmonics » Post Topic » Composition over Inheritance in Game Entities said

    am February 11 2009 @ 11:33 am

    [...] just answered a question on another blog, which I thought was worth reposting on it’s own [...]

  8. Sidar said

    am July 28 2009 @ 6:24 pm

    Hi,

    When i open the example from googleCode. I see actually brackets with codes.
    However here they are left out.

    Im typing all this stuff over for learning purposes, so I’m confused right now.

    I did i missed something i should have read?

    greetings,
    Sidar

Comment RSS · TrackBack URI

Leave a comment

Name: (Required)

eMail: (Required)

Website:

Comment: