-
Notifications
You must be signed in to change notification settings - Fork 0
How messaging works
The platformer engine uses a component-based structure for entities.This means an entity's functionality is determined by the pieces (called components) that make it up. These components are designed to be self-contained and reusable in multiple types of entities. Thus components, for the sake of re-usability, do not directly call functions in other components. Instead, components use a loosely-coupled messaging system to handle communication between components in a single entity and between components across entities.
#Listening for a Message The messaging system is built into an entity, such that whenever an entity receives a message (ie. a message is triggered on an entity), the message is handled by all of the entity's components that are listening for that message. An entity knows which components are listening for which messages because the components themselves bind appropriate handlers to the messages. Which messages a component binds to is set by the list of event handlers sent to the component factory:
platformer.createComponentClass({
id: 'name-of-component',
constructor: function(definition){},
events: {
"load": function(resp){
// Run event handling code here
}
// List additional handlers if needed
}
});
#Sending a Message
To communicate with another component on an entity, a component sends a message to its owner entity. The entity will then pass it onto the listening component.
The function that does this is trigger() (found in Entity) or triggerEvent() if it's a single event ("trigger" can also accept an array of events). The call would look something like this:
this.owner.trigger('message-name', messageData, false);
'message-name' is the message id that the other component is listening for. 'messageData' is the content of the message. This can be a value or an object. The third parameter turns the message tracking on or off for this message. The message tracking will log the message contents to the JavaScript console. You can also turn message debugging on when you send messageData that is an object with a 'debug: true' key/value pair.
##Messages Between Entities To send a message between two entities, there are a few methods we use. If you are creating a component and have a reference to the entity that you need to talk to you can simply do:
entity.trigger('message-name', messageData);
Thus calling the message on only that entity.
If you don't have a reference to the entity you need to send a message to or are building out an entity using components, there are several components that can be used to manage messages: broadcast-events, entity-container, and entity-linker.
###Broadcast-Events
broadcast-events takes a received message and broadcasts it to different portions of the game. It can broadcast it game-wide, to the parent of the current entity, and to its own entity (useful when you need to remap the message id). Game-wide broadcasts are sent to the scene which broadcasts them to the current layer entities, which sends them to all their components. The parent broadcasts go to the parent of the entity, which in most (but not all) cases is the layer. Entity broadcasts are sent to the entity that the broadcast-events component is on.
Setting up the broadcast-events component looks something like this. The events, parentEvents, and renameEvents are the game-wide, parent, and entity broadcast event definitions. The first field is the message the broadcast-events component is listening for, the second field is the message it will send. The message data that the triggering message contains will be transferred to the new message.
{
"type": "broadcast-events",
"events": {"broadcast-gem-collected": "gui-gem-collected"},
"parentEvents": {"broadcast-gem-collected": "gui-gem-collected"},
"renameEvents": {"broadcast-gem-collected": "gui-gem-collected"}
}
###Entity-Container
entity-container is a component that is used to hold references to children entities. It is frequently used in layers to hold all the entities on a layer.
The entity container sends several messages when entities are added or removed from it. These messages are: 'child-entity-added', 'peer-entity-added', 'child-entity-removed', and 'peer-entity-removed'. The 'child' messages are sent to the owner of the container, while the 'peer' messages are sent to all the other entities in the container. These messages include a reference to the entity added and are useful when you need a reference to one of the objects in the container.
The entity-container can also rebroadcast messages it receives to all of its children. This is done by defining a list of childEvents like this:
{"type": "entity-container",
"entities": [
{"type": "an-entity"}
],
"childEvents": ['rebroadcast-me']
}
In this case, the entity-container has one object in it 'an-entity' and one child event 'rebroadcast-me'. Now, when the entity container receives a 'rebroadcast-me' message it will send it to all the entities it contains.
###Entity-Linker
entity-linker is used to set up a channel that two or more entities can communicate on. Its behavior is similar to the broadcast-events component except that it only triggers events on the other connected entities, linked by a common linkId and specified in the components' JSON definition like this:
{"type": "entity-linker"
"linkId": "friends",
"events": {
"bored": "lets-play"
}
}
In this example, if the entity to which the above component is attached hears a "bored" event, it will broadcast "lets-play" on the linked "friends" channel, triggering "lets-play" on every other entity also having an entity-linker component with "friends" as its linkId.
##Connecting The Pieces So, to send a message from one entity to another, you could add a broadcast-events component to the entity sending the message and use its game-wide broadcast feature to send a message to the Scene which would then pass the message to its layers. In the layer you add the message id of your message to the entity-container definition so that the message will be sent to all the entities contained inside. Or for a more direct connection, set up an entity-linker with the same linkId on each entity that should be in on a given conversation. In this way, the entity listening for a given message will receive it.
Platypus was developed by PBS KIDS and Gopherwood Studios. It is free to use (see licenses.txt), all assets in the example games are © Gopherwood Studios and/or © PBS KIDS.