13
\$\begingroup\$

I want to make an Event scheduler for my Game, I basically want to be able to schedule the triggering of a Game Event. This can be a one time trigger, or a periodic trigger (trigger event "E_BIG_EXPLOSION" on a 5 seconds basis...).

It is tempting to think that this may be a good place to use a Singleton, but singletons can be quite evil and they tend to spread like a disease... so I try to avoid them at all cost.

What design would you propose to avoid the singleton usage in this case?

\$\endgroup\$
1

3 Answers 3

12
\$\begingroup\$

You should have a very well-defined set of interfaces that are allowed to transmit or receive messages -- giving them a reference to a EventScheduler should be trivial. If it isn't, or if you feel like that would involve passing the event scheduler to "too many" distinct types, then you might have a larger design problem on your hands (a promiscuous dependency, which singletons tend to exacerbate, not solve).

Remember that while the technique of passing the scheduler to the interfaces that need it is a form of "dependency injection," you aren't in this case injecting a new dependency. This is a dependency you already have in the system, but you are now making it an explicit one (versus a singleton's implicit dependency). As a rule of thumb, explicit dependencies are more preferable as they are more self-documenting.

You also afford yourself more flexibility by decoupling the consumers of the event scheduling from each other (since they are not all necessarily tied to the same scheduler), which can be useful for testing or simulating local client/server setups or a number of other options -- you may not need these other options, but you have not expended effort to artificially restrict yourself from them, which is a plus.

EDIT: All I mean when I talk about passing the scheduler around is this: if you have some game component that is responsible for responding to collision, it's probably created via some collision responder factory that is part of your physics layer. If you construct the factory with a scheduler instance, it can then pass that instance to any responders it creates, which can then make use of it to raise events (or perhaps subscribe to other events).

class CollisionResponderFactory {
  public CollisionResponderFactory (EventScheduler scheduler) {
     this.scheduler = scheduler;
  }

  CollisionResponder CreateResponder() {
    return new CollisionResponder(scheduler);
  }

  EventScheduler scheduler;
}

class CollisionResponder {
  public CollisionResponder (EventScheduler scheduler) {
    this.scheduler = scheduler;
  }

  public void OnCollision(GameObject a, GameObject b) {
    if(a.IsBullet) {
      scheduler.RaiseEvent(E_BIG_EXPLOSION);
    }
  }

  EventScheduler scheduler;
}

This is obviously a terribly contrived and simplified example since I don't know what your game object model is; it does however illustrate making the dependency on the event scheduler explicit and shows some potential for further encapsulation (you wouldn't necessarily need to pass the responders the scheduler if they communicated through to a higher level collision response system at the same conceptual level as the factory that dealt with the nuts and bolts of raising events via the scheduler. This would isolate each individual responder implementation from the implementation details of the event dispatch system, such as which specific event to raise on collision, which may be ideal for your system -- or not).

\$\endgroup\$
3
  • \$\begingroup\$ Thanks for your answer, I thought about dependency injection. It would be very nice if you could specify your solution a bit better? (Pseudo-Code? Diagram?). I think I follow your idea, but maybe it's just my own interpretation of the concept. \$\endgroup\$
    – Mr.Gando
    Aug 5, 2011 at 16:13
  • \$\begingroup\$ It's hard to do that in a way that's useful without knowing what classes of yours send/receive events to the scheduler. \$\endgroup\$
    – user1430
    Aug 5, 2011 at 16:14
  • \$\begingroup\$ In my Engine, any Game Entity can have an "Event Dispatcher" component attached... \$\endgroup\$
    – Mr.Gando
    Aug 5, 2011 at 16:19
7
\$\begingroup\$

An event dispatcher is one of those cases where a singleton isn't the worst idea in the world, but I applaud you for trying to avoid it. You might find some ideas here.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ Thanks!, each time a singleton is created a Kitten Dies ;) \$\endgroup\$
    – Mr.Gando
    Aug 4, 2011 at 16:15
3
\$\begingroup\$

I tend to avoid singletons too but there are a few objects that make the most sense as singletons and a central messaging system is one of them. Despite the rants I've heard, singletons are certainly much better than global variables/functions because you always have to deliberately address it (versus global values just magically appearing out of thin air).

In the end every message sender and receiver must have some common point of intersection, and it is much better to keep your objects decoupled by having a common singleton shared by everything rather than have each of your message senders directly know about the message receivers.

While I'm sure some other architecture could be devised for your event system, to me it seems like a waste of effort to over-think it, especially when using an event system is already a big win over not using one.

EDIT: As for your specific example of an explosion event dispatched on a periodic trigger, I would probably have the events dispatched in some other object (like the turret gun or whatever causing those explosions) and not in the central event system. However those events would still be dispatched to the central event system.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .