Skip to main content
gamedev.net
🔒 Locked

Inter-module communication

Started by stormwarestudios Mar 17, 2009 at 7:42 PM 0 replies 1k views
Original Post
stormwarestudios
stormwarestudios
Hello all, I'm trying to decide what is the 'best', or 'cleanest', or 'most future-friendly' method of handling inter-module communication in my game. Currently, I've got two queues set up: one queue is for incoming network communication, and the other is for application-module communication. All queues are thread-safe. The way the engine works, when the network client thread is invoked, it begins collecting incoming packet events, and tossing them on the packet queue. The main application loop is responsible for inspecting the network queue, popping one packet event per frame, and handling it. The main application loop is also responsible for inspecting the application event queue, and handling these events as well. The network client only talks to the packet event queue. The application event queue is a singleton (gasp!) which may be invoked from any other module (graphics, sound, input, etc) in order to enable each module to create its own events. For example, when the player does pretty much anything in the game, either one of the input modules (mouse or keyboard) must work in cooperation with the graphics module (which has sub modules, the work-horse of which is the scene manager) to determine the object(s) the player wishes to interact with, then send a request via the network client (directly, no queue touching) to the server. A problem I've encountered is the difficulty of utilizing class members cross-module. In the above example, if the player clicks the mouse cursor, the engine must (a) determine the 3d coordinates in the world that the player clicked, (b) perform a raycast to determine the scene object affected, (c) send the click request to the network client as a use/examine/take/invoke command, with the object's ID. In this example, three different modules need to communicate (in order, Input, Scene, and Network). As I write this, I'm seeing different ways of handling this, and I think I need to spend more time working on my SDL flowcharts to figure out the flow of events for each command-type. In short, I'm not sure whether I should: 1) Make everything singletons, and do away with queues entirely. Involves engine overhaul. 2) Make the network client a singleton, and expose as much of each module as need be to each other module (through passing of module-object instance pointers at allocation time). Most attractive. 3) Add a 'destination' value to application events, which helps me determine what the ultimate destination of the event is. Pursue #2. Could be confusing, and sounds like it's prone to bugs. 4) Expand on my application events, such that there is no need for #3. Stick with #2. Might also involve expanding the packet event protocol, since there are events there too that are used for incoming and outgoing. 5) ???? I'd like to hear how anyone else might have gotten themselves out of such a situation. I've come to the conclusion, based on vocalization of nay-sayers, that singletons are an F-word around Gamedev. I'd appreciate to hear alternatives, if anyone needs to point out that their usage is baneful to the existence of Mankind.
Captain P
Captain P
Quote:
Original post by DarkHorizon
The application event queue is a singleton (gasp!) which may be invoked from any other module (graphics, sound, input, etc) in order to enable each module to create its own events.

Why do all events need to go through a single channel? Can't they communicate directly to the modules that they need to talk to, by means of function calls?

Quote:
For example, when the player does pretty much anything in the game, either one of the input modules (mouse or keyboard) must work in cooperation with the graphics module (which has sub modules, the work-horse of which is the scene manager) to determine the object(s) the player wishes to interact with, then send a request via the network client (directly, no queue touching) to the server.

Input should not know about graphics, or even care about that sort of thing. Input just checks for input and fires off events to, or allows polling by, external code.

Now, the current active menu, or the game itself, should use the input module - and upon input, it should "do it's thing". Which, in this case, means asking the renderer module to do a ray-trace, to retrieve the selected object. And then, depending on the game rules, using the network module to send some information. Note that the input, renderer and network modules are mere 'services', used by higher-level code, without notion of each other.

Quote:
1) Make everything singletons, and do away with queues entirely. Involves engine overhaul.

I don't see the need for singletons here at all - if you need a single, globally accessible instance, just create a single global instance.

Quote:
2) Make the network client a singleton, and expose as much of each module as need be to each other module (through passing of module-object instance pointers at allocation time). Most attractive.

As demonstrated above, modules likely do not need to interact with each other as much as you think. Keep down the number of dependencies and your code will be easier to maintain.

Quote:
3) Add a 'destination' value to application events, which helps me determine what the ultimate destination of the event is. Pursue #2. Could be confusing, and sounds like it's prone to bugs.

How about the following: the input module is an event sender, and menus can register to it to receive events directly (by using an event-listener interface, an event sender simply needs to keep a list of listeners, and any code that needs to receive events can derive from the listener interface class). This way, only the code that needs to know about certain events will get to know - and it will need to explicitely register for them, which makes it very clear who needs to know what.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.