Decoupling modules using events

Gameplay code can be a complex beast. In many cases, there are complex, many-to-many relationships between all sorts of different game entities. This can be good for the player, as he or she might enjoy the interesting emergent patterns of behavior created by this kind of game object interconnection.

For the programmer (that is you), who has to think about and write all the code that makes this happen, things look different, though. Having the game entity that creates an event which holds references to all the objects that will react to it could be problematic. This could lead to chaotic, messy code and a great deal of unnecessary coupling between otherwise independent and differing types of objects. The more complex the code, the more you need to create a more modular and maintainable design.

From a software engineering point of view, this situation cries out for a form of publish/subscribe design pattern that allows game entities (and other kinds of objects too, of course) to send and react to messages without knowing about the specific senders or receivers of the message.

Panda3D provides such a neat messaging subsystem, which we will take a look at in this recipe.

Getting ready

This recipe builds upon the project structure described in Setting up the game structure found in Chapter 1. Please follow these instructions before going on with the current recipe.

How to do it...

Follow the following instructions to learn how to use Panda3D's messaging system:

  1. Edit Application.py so it contains the following code:
    from direct.showbase.ShowBase import ShowBase
    from direct.interval.IntervalGlobal import *
    from direct.showbase.DirectObject import DirectObject
    from panda3d.core import *
    class Sender(DirectObject):
    def start(self):
    smiley = loader.loadModel("smiley")
    pause = Sequence(Wait(5), Func(messenger.send, "smiley-done", [smiley]))
    pause.start()
    class Receiver(DirectObject):
    def __init__(self):
    self.accept("smiley-done", self.showSmiley)
    def showSmiley(self, smiley):
    smiley.reparentTo(render)
    class Application(ShowBase):
    def __init__(self):
    ShowBase.__init__(self)
    self.cam.setPos(0, -10, 0)
    rec = Receiver()
    snd = Sender()
    snd.start()
    
  2. Press F6 to start the program.

How it works...

In our little event sample, we create the classes Sender and Receiver that are communicating without ever knowing about each other's existence.

In the start() method of Sender, we load the smiley model and wait five seconds before sending the"smiley-done" message, passing the smiley model reference as a parameter to the messenger.send() method that adds the message to the global message queue of Panda3D.

By calling accept() in its constructor, each instance of Receiver subscribes to the"smiley-done" message. As soon as a Sender dispatches this message, the showSmiley() method will be called. This method reparents the smiley model to the scene root to make it visible.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset