So I took the code from my recent journal entry and started working it in. It's heavily inspired by Unity's model. In Unity, the base GameObject is both a scene graph and a component container. In Unity, the GameObject is also a sealed class, which prevents you from inheriting from it. You're stuck with what they give you.
The "base" components I've put in place so far:
- Transform - A 2d transformation component which holds position, rotation, scale and things to do with placement in the world
- Camera2d - A 2d camera which is the "window" on the world
- Renderer - A 2d sprite renderer
- Behaviour - A base component which is intended to form the basis of custom logic
Using these 4 components I've been able to pull apart my previous efforts and compose my world. I've then split apart my existing game logic into several other behaviour components. This includes everything from movement, targeting and weapon fire.
There's a few things I've noticed from Unity's implementation, and therefore mine. Most (in fact almost all) GameObjects have a Transform component. So many, in fact, that I've chosen to create one on default construction of the GameObject and have added a shortcut property on GameObject which lets me get to the Transform quickly. I've also followed Unity's lead and added a GameObject property to retrieve the object which this component is attached to.
It's interesting as some Component-Entity models dictate that components can only communicate with others via messaging. That is, all components have no knowledge of each other or direct access to each other. Unity's model breaks this in half, and suddenly you're able to access other components on your object (or indeed other objects) by accessing this.GameObject.Transform, and so on. Personally, I don't mind this. In my system, the Renderer needs to know the position of an object, and many behaviours need to modify it.
Right now I'm looking at the Scene Graph part of GameObjects. You can attach and remove them to each other and cascade Update() calls, but I'm looking at the matrix transform aspect of it now to allow you to set child objects relative to their parents. That won't take long to sort out.
I'm looking at adding a generic messaging and/or event system to the GameObjects/Components. This would allow other objects to subscribe and react to asynchronous messages from others. This would be handy for damage events, or anything else that needs to observe events from others.
I'll probably post another update with some details of the implementation.