Skip to main content
replaced http://gamedev.stackexchange.com/ with https://gamedev.stackexchange.com/
Source Link

EDIT Liosan's answerLiosan's answer is sexier. Look into it.

EDIT Liosan's answer is sexier. Look into it.

EDIT Liosan's answer is sexier. Look into it.

deleted 1 characters in body
Source Link
michael.bartnett
  • 7.6k
  • 1
  • 36
  • 45

EDIT Lionsan'sLiosan's answer is sexier. Look into it.

EDIT Lionsan's answer is sexier. Look into it.

EDIT Liosan's answer is sexier. Look into it.

Source Link
michael.bartnett
  • 7.6k
  • 1
  • 36
  • 45

EDIT Lionsan's answer is sexier. Look into it.


Like Markus said, messages aren't a common candidate for object pools. Don't bother with it for the reasons he mentioned. If your game sends tons of messages of specific types, then maybe it'd be worthwhile. But then at that point I'd suggest you switch over to direct method calls.

Speaking of which,

Can't send a message to a specific recipient, but I haven't needed that yet in my game so I don't mind it too much.

If you know a specific recipient you want to send it to, wouldn't it be pretty easy to get a reference to that object and do a direct method call on it? You could also hide specific objects behind manager classes for easier access across systems.

There's one con to your implementation, and it's that there's the potential for lots of objects to get messages that they don't really care about. Ideally your classes would only receive messages that they actually care about.

You can use a HashMap<Class, LinkedList<Messagable>> to associate message types with a list of objects that want to receive that type of message.

Subscribing to a message type would look something like this:

globalMessageQueue.subscribe(PlayerDiedMessage.getClass(), this);

You could implement subscribe like so (forgive me some mistakes, haven't written java in a couple of years):

private HashMap<Class, LinkedList<? extends Messagable>> subscriberMap;

void subscribe(Class messageType, Messagable receiver) {
    LinkedList<Messagable> subscriberList = subscriberMap.get(messageType);
    if (subscriberList == null) {
        subscriberList = new LinkedList<? extends Messagable>();
        subscriberMap.put(messageType, subscriberList);
    }

    subscriberList.add(receiver);
}

And then you could broadcast a message like this:

globalMessageQueue.broadcastMessage(new PlayerDiedMessage(42));

And broadcastMessage could be implemented like this:

void broadcastMessage(Message message) {
    Class messageType = message.getClass();
    LinkedList<? extends Messagable> subscribers = subscriberMap.get(messageType);

    for (Messagable receiver : subscribers) {
        receiver.onMessage(message);
    }
}

You could also subscribe to message in such a way that you can split up your message handling into different anonymous functions:

void setupMessageSubscribers() {
    globalMessageQueue.subscribe(PlayerDiedMessage.getClass(), new Messagable() {
        public void onMessage(Message message) {
            PlayerDiedMessage msg = (PlayerDiedMessage)message;
            if (msg.livesLeft <= 0) {
                doSomething();
            }
        }
    });

    globalMessageQueue.subscriber(EnemySpawnedMessage.getClass(), new Messagable() {
        public void onMessage(Message message) {
            EnemySpawnedMessage msg = (EnemySpawnedMessage)message;
            if (msg.isBoss) {
                freakOut();
            }
        }
    });
}

It's a little verbose, but helps with organization. You could also implement a second function, subscribeAll that will keep a separate list of Messagables that want to hear about everything.