Wednesday
Nov242010
An introduction to our component architecture - what we started with
Wednesday, November 24, 2010 at 10:50PM Update (Sep '11): I've posted about this more recently here -- Lightweight component architectures and object composition
This week's #idevblogaday post serves two purposes:
- It saves me some time (this is the first week where I'm really struggling to get sufficient time to write a whole post)
- It's given me the kick up the back side required to move this research (the component architecture) forward
What I'm sharing below is the first draft of a description/outline of the component architecture we've developed. It's a work/piece of research in progress, so bear in mind that:
- It is not complete
- It is not contemporary (the version we're now using makes changes)
- I will post more up to date information about this archictecture in the coming weeks and months
So, without further adue...
"Dead West" Component Architecture Version 0.1
Context - http://cowboyprogramming.com/2007/01/05/evolve-your-heirachy/, and in Bjarne Rene: Component Based Object Management. Game Programming Gems 5, 2005, page 25. More links and OO-comparison video here - http://www.learn-cocos2d.com/2010/06/prefer-composition-inheritance/.
The Dead West (36peas - it’s deliberately generic) component architecture:
The Dead West (36peas - it’s deliberately generic) component architecture:
- Composes game objects from behaviours and data - not from an object hierarchy
- Uses an object hierarchy only for Game World > Game Object > Behaviour
- Broadcasts (and narrowcasts) messages throughout the game world
- Encourages messaging over explicit references (game objects should not normally keep references to one-another in the long-term) - even where references are kept, they should only be kept to narrowcast messages
- Templates allow for behaviours to be grouped into logical, abstract concepts - e.g. there is a template for a Hero
- Templates can implement other templates - e.g. the Farmer template can implement the Hero template
Notable stores and methods noted below - does not include obvious glue methods and debug/logging methods.
DWGameWorld (GW)
Manages the game by virtue of owning the set of gameObjects.- localStore contains world-level data.
- doUpdate: is the entry point for delta-based update methods (passed from here to objects and ultimately behaviours)
- handleMessage: broadcasts messages to the entire game world
- attaches to the rendered world by virtue of initWithRenderLayer:
- addGameObjectWithTemplate creates new game objects in the world based on the provided template
DWGameObject (GO)
Represents a single object in the game - a hero, enemy or non-rendered item such as a trigger, spawn point etc. The DWGameObject object itself provides little more than a container for its behaviours and a store for shared data.- localStore (NSMutableDictionary) contains all data for that object
- addBehaviour: withData: add the specified behaviour to the object, if not already in the object’s behaviour list. Will always write the data passed, including overwrites of existing data.
- loadData: loads (and overwrites) data passed - pass a single-key dictionary to load just one key/value pair
- doUpdate: calls doUpdate on all behaviours
- handleMessage: passes message to all behaviours - can be used as messaging entry point for narrowcast messages
DWBehaviour
Base class for behaviours.- localStore (NSMutableDictionary) contains all data for this instance of this behaviour - shared data should only be stored in the host DWGameObject
- handleMessage: does nothing in base class definition - see DWBTest.m for sample implementation
- doUpdate: does nothing in base class abstract definition - see DWBTest.m for sample implementation
See DWBTest.m for a sample implementer of DWBehaviour.

DWMessage
Data object for passing messages through the game world.- messageType type of message (as defined in DWModelConstants.h)
- payload the message detail/payload
- game world: [gw handleMessage:m];
- to specific GO: [go handleMessage:m];
- from behaviour, to host GO: [myGo handleMessage:m];
Templates
See templatedefs-general.plist - specifically the Dictionary keyed DWTModel for the data definition for templates.

Constants
DWModelConstants.h defines:- model load/save key constants
- DWMessageType enum
- (doesn’t, but implied that it will) behaviour names (keys - same as object names)
Additional notes:
- Does not accommodate UI external to the game world - messages in and queries out should facilitate this
- A template can implement other templates that specify the same behaviour. Loading order of implemented templates is not guaranteed, but behaviours specified directly by the host template will be loaded last, meaning data specified there will overwrite that written by any implemented templates.
- GO data defined in template is written last (it will overwrite any class-level, implemented-template-behaviour-level and behaviour-level data)
- Behaviour implementation classes can (do and should) write their own data defaults in initWithGameObject - see DWBTest.m for an example.
Outstanding issues/undecided:
- Do behaviours need a processing order - in which doUpdate would be passed to behaviours based on their priority/classification. If so - easiest method would likely be storing processing priority (+/- integer with 0 as default) on behaviour definition, then creating a sorted list of behaviours on GO creation - assuming GOs don’t get behaviours added later
Reader Comments (4)
I would love a followup to this with an overview of how its working for you, and have you noticed a big change in adding new content to a game. Why you felt it was necessary, etc... More of an overview of how it integrates with your projects
@Sim - I'll certainly be doing that. You'll have to bear with us as we catch up on stuff but I plan to write quite a bit more on:
- the current form of the architecture (how we've evolved it to fit)
- how we use it to architect games themselves (we've three clearly different examples)
- how much easier it makes iterative game development (a lot ;])
G.
This is really great, thanks for sharing. I love reading about other people's architecture and approach to handling entities and messaging. Mine is based around state machines and NSNotificationCenter but I'm not entirely happy with it, this is definitely food for thought!
@dave - I've done a fair bit state machine-based architecture design in the past. The ongoing flexibility of a component architecture (which isn't really a fair comparison anyway) is something of a relief.
I'd not looked at NSNotificationCenter before designing the outline of this, and for our purposes don't need anything more sophisticated. I did have general platform agnostic compatibility in mind as well at the time -- although objective-C itself lends itself so well to messaging-based architectures that I suspect that there'd be a good amount of work to do to port it.
G.