I'm trying to make my code more organized and structured. I thought to have things such as a render system, input system, etc and have a message system send messages between each system. Sometimes I need data with the message like for example more than one system needs access to the directx device so I would like to pass that around. I had something that I was trying to make work but then halfway through I realized there was a circular dependency in the headers that I couldn't resolve. So what's a good way to pass data between your different systems?
Passing data with message system?
You will have to iterate multiple ways (depending on your skill level) on your system's api before you get to a state where it's clean and easy to understand what that system needs.
I would advise AGAINST an explicit message system between systems, and I would focus more on cleaning the API of the system you're currently working on.
So For example, if one of your renderer's call is:
void DrawCube(GameWorld* world, GameAssets* assets, GameDatabase* database, Vec3 position, Vec3 dimension, Vec4 color)
Then you should probably start investigating why that call needs the world, the assets and the database pointers, as logically a renderer wouldn't need those.
Probably you need just some parameters taken from them, and so your call can then become:
DrawCube(DrawCubeParams params, GameAssets* assets, Vec3 position, Vec3 dimension, Vec4 color)
where the caller sets all the necessary params.
I personally think that this is the only way one can get to clean and good api.
Leonardo
I guess it depends on how you are handling the demarcation of the "systems", are they separate programs or? I would almost see the development of a messaging system inside the same program as unnecessary overhead. It could lead to better organized code, for sure, but what does it do to performance? Are you creating extra work for these separate systems(creating/reading messages)? How much extra time does it add to a single process, would there be acknowledgements/retries involved? Not trying to rain on a parade here, sorry for that.. Just asking questions. I use messaging between different programs actively(just udp currenly), I'm just trying to see a practical use for it inside one.
Current WIP: https://www.gamedev.net/projects/1006-sling-bot-boarding/
Play it here(Chrome or FF): https://www.kongregate.com/games/WilliamOlyOlson/slingbot-boarding
2 good videos on the subject. The first one with our own Sean Middleditch. Also check out the other videos on both channels.
🙂🙂🙂🙂🙂<←The tone posse, ready for action.
I would suggest the first important piece is to decide is which systems need to communicate with each other first. Once you have that you can figure out what, when and how often your systems need to communicate. IMO systems that do infrequent, one way, communication are great candidates for message passing schemes. The sender is decoupled from the receiver and for implementations like the observer pattern the overhead for sending messages is usually lower than alternatives like polling.
I also second what @erpeo93 is saying. Try not to get too attached to one solution to a problem. For many basic problems in system-system communications a bog standard function call can do the job quite nicely.
11 hours ago, erpeo93 said:[elided]
void DrawCube(GameWorld* world, GameAssets* assets, GameDatabase* database, Vec3 position, Vec3 dimension, Vec4 color)
Then you should probably start investigating why that call needs the world, the assets and the database pointers, as logically a renderer wouldn't need those.
Probably you need just some parameters taken from them, and so your call can then become:
DrawCube(DrawCubeParams params, GameAssets* assets, Vec3 position, Vec3 dimension, Vec4 color)
where the caller sets all the necessary params.
I personally think that this is the only way one can get to clean and good api.
Leonardo
This above could be pared down further. A barebones renderer shouldn't need to know how game assets are managed, what an asset is or even that it's being used for a game (vs any other real time rendering application.) The renderer only needs to know about data that you intend to pipe into the GPU.
DrawCube(Matrix4x4 worldTransform, Material material);
The worldTransform covers location, size and orientation of the object. The remaining transforms (view and projection) would be handled elsewhere since they're normally common across many draw calls. The material covers everything else pretty much. From here you could then make a more abstract function which DrawCube can use behind the scenes.
DrawMesh(Mesh mesh, Matrix4x4 worldTransform, Material material)
As a side note, if you're rendering objects using an API like this what you'll likely need to do behind the scenes is queue something to be rendered instead of rendering immediately. Once you start using stuff like multipass shaders, render targets and postprocessing drawing objects on screen becomes a lot more work than simply rendering a box at a position via a draw call. Even without that you'd should probably sort your actual GPU draw calls for various reasons.
Finally, a warning from personal experience, if you want to make games it can be a good idea to stay away from engine code until you get a game or two under your belt. Engine code is a huge massive crazy time sink and if you're not sure what you want the engine to do there's lots of intellectual tarpits and blind alleyways to get lost in on your way to something useful. It's pretty fun if you want to do it but you're not going to be making many games very quickly. Be ready to throw away a lot of code as you learn what designs do and do not work well.