I'm working my way through a lot of game development resources, coming from a completely different field of software development, I'm interested in learning what patterns are frequently used in game development, and which aren't.
During my research, I wanted to know if/how event queues are handled in games, and came across Game Programming Patterns' post about Event Queues. (as an aside, what an awesome resource that book is!)
In it, Bob Nystrom gives an example of a "play audio" queue, where one part of the system can produce/enqueue the playing of an audio fragment, and the audio handler/consumer can act on that request whenever it can.
I like this pattern a lot, but the end-result still feels like it results in domains being crossed, because the sender (in this example the part of the system that deals with a unit dying) has to ask the audio system to play the "deathSoundID" sound using playSound(deathSoundID)
(which, in this case, then enqueues that request for the audio engine to pick up as soon as it can).
What I expected to be proposed is that the sender in this case tells the audio engine that an event occurred (by having the audio engine listen for events from this specific game system), at which point the audio engine can then determine if/how it wants to act on that specific event.
Now, admittedly, there's still crossing of domains here, as in my example, the audio engine now has to have some kind of (huge) case statement that couples any game event to an audio-related action, but you no longer have to litter unrelated functions with calls to playSound
, and it also forces you to be a good citizen, and allow other systems to act on whatever action you just took, be it the audio engine in this case, or the "gamepad rumbler" engine that wants to rumble your gamepad because you've just slain a large enemy.
Another downside to this is that you need many more queues for all your systems (if you want to avoid some kind of global event queue, which I think you should), which might not be practical/performant enough to do, so perhaps that's the reason why it wasn't chosen here.
Either way, as a newcomer to game development, I'm interested to hear why one would be preferable over the other, and in what situations that would be the case.