after one year of interruption in game development I am about to restart my work. Before starting however I would like to clarify some questions about software architecture which are unclear to me and led to some confusion/uncertanity in the past.
My goal here is not only to code a game but also to learn about Software architecture in the context of game development.
In my last project I implemented the behaviors of my spatials in scene by using controls almost exclusively (For example: NewtonianControl, DamageControl, ProjectileLauncherControl, PlayerControl …). I did so because I was defining my spatials as game objects what is obviously wrong. However it worked for me at the beginning. I could use the SceneComposer, attach the controls to the spatials and add the behaviors I intended. But at a point of complexity this concept broke down because doing so started feeling like breaking with the control concept. For example the basic requirement of adding new scene content (for example a bullet, nozzle fire etc…) required additional workaround which made me feeling like abusing the Control interface. The reasons were:
- Controls do not include AssetManager and RootNode by default So scene modification is cumbersome and obviously out of scope of the control interface. You have to attach an AppState as a system object for this and to connect the controls with it or: Take the assetManger/rootNode from the load/onRender method.
But even worse:
- Controls are not executed if the spatial is detached from the scene (e.g. vessel in hangar or out of sight). So the game objects cannot be taken away from scene without interrupting the update. ==> Artificial node with an artificial update thread?? No way!
–> Obviously the game logic had to be decoupled from the spatial update. What about AppStates?
On the other hand when I define AppStates as game objects there are different problems.
- AppStates are not savable by nature so they are not supposed to be made persistent (loading/saving, sure I know about implements Savable but it also feels like breaking with the concept by adding additional responsibility)
- Where do I then store the internal state of the Game object to make it persistent?
- How do I then load the models build with SceneComposer (containing data like HP/HPMax) and attach them to the correct AppStates (because I cannot attach AppStates to Spatials bcz. they do not implement Control interface by nature).
- Can/Shall I have savable “extends AbstractControl implements AppState” objects with redundant update loop? Or savable appState delegates?
So I came along defining one singleton SceneAppState/Control observer object managing all dynamic objects (Ships, Bullets, moving turrets etc… equipped with the correct control composition in SceneComposer), one PlayerAppState (with the input) and ContentAppStates for individual non persistent procedural element (like planets, stars etc…).
In order to increase the fun: There shall be nested game objects like Vessels with fully controllable turrets, engines, antennas… Or procedurally generated planetary systems with planets, orbits, moons, with surface tiles and collision etc… To link them with the scene seems to be a challenge.
Do you have any suggestions? Because I think what I really need is something like a cooking reciple for architecture and design decisions like:
- You want to use XXX then you should implement/extend YYY class/interface.
Thanks in advance…