Based on a question I previously asked here regarding to decoupling input from other components of an entity I developed a small component architecture on top of XNA to understand how everything works and plays together. Basically, my architecture has the following components/services/systems:
Game
This is the root of any game, responsible for ticking the game loop (updating, drawing) as well as instantiating all systems.
GameModule
A game module responsible for a certain aspect of the game, such as UI (UIModule), input (InputModule), animations (SpriteAnimationModule), scenes (SceneStackModule) etc.
Scenes
Holds the current state of the game. Basically an entity manager. :)
Entity
Entity which only holds a collection of components and very basic world space information such as position, rotation etc.
Component
A component of an entity, which can be anything (SpriteComponent, ScriptComponent, ControllerComponent)...
However now I seem to have a problem of the responsibilities between my game systems (modules) and the components, which are not aware of each other. For instance, I have an UIModule instantiated in my game, which I need to update/render before any other systems in order to appropriately handle input events on the UI. For this, I'd need to loop through all UIComponents - which are unfortunately encapsulated within the current scene. Which in turn is only accessible via the SceneStackModule (LIFO collection for scenes). So I have to either make my UIModule aware of the concept of scenes (by making the SceneStackModule a dependency of the UIModule), create an UIModule for each scene or make the UIModule a dependency and register the UIComponent twice (once in the entity, once in the module).
Approach 1
public class UIModule : GraphicalModuleBase {
public UIModule(SceneStackModule sceneStack) { }
public void Draw(GameTime gameTime) {
var uiComponents = SelectUIComponentsFromEntities();
uiComponents.Draw(gameTime);
}
}
Approach 2
public class MainScene : Scene {
public UIModule UIModule { get; } = new UIModule();
public void Draw(GameTime gameTime) {
var uiComponents = SelectUIComponentsFromEntities();
uiModule.Draw(gameTime, uiComponents);
}
}
Approach 3
public class UIComponent : ComponentBase {
public UIComponent(UIModule uiModule) {
uiModule.RegisterComponent(this);
}
}
All three approaches are not very nice (why does the UI need to be aware of scenes, why no components need modules as dependencies or why do I have to declare my 'main render logic' (UI before everything else) a part of every scene?). So I either clearly missed something here or that's another nasty part of game development. :/