-
Notifications
You must be signed in to change notification settings - Fork 0
Handle input
#Initial Setup The game engine is set up to handle keyboard, mouse, and touch input. To plug up a controller, there are two components required to make it function:
-
Handler-Controller - This component should be placed at a scene's layer level and fires a controller message to all
entity-controller
s on that layer. - Entity-Controller - This component should be attached to every entity that should listen for controller input events.
The first step is to identify the scene layers that should listen for input. This will likely include the action layer where the game world exists to control the hero, but it may also include GUI layers where touch controls may reside outside of the game world layer. Once the layers have been identified, add a handler-controller
component to each layer's list of components. Ideally this component should be placed prior to any logic components (typically Handler-Logic) so that entity logic components will have the updated controller state from the current tick.
The second step is to identify all the child entities that expect input messages. A common entity listening for controller input would be the game hero, so adding an entity-controller
component may cause the entity definition to look something like this:
{
"id": "hero",
"components":[{
"type": "entity-controller"
},{
"type": "logic-directional-movement"
},{
"type": "render-debug"
}]
}
#Keyboard Controls
Now that the two most important components are in place, the next step is to determine the controls. If we want our hero to walk left and right, we may want to map the left arrow to the hero walking left and the right arrow to the hero walking right. For the Entity-Controller component, this is called a controlMap
, mapping inputs to actions. The inputs we are listening for are the left and right arrow keys, and by looking at the messages that our Logic-Directional-Movement component is listening for, we know that we want to map these inputs to "go-left" and "go-right" messages. So our hero definition with the new control mappings may look something like this:
{
"id": "hero",
"components":[{
"type": "entity-controller",
"controlMap": {
"key:left-arrow": "go-left",
"key:right-arrow": "go-right"
}
},{
"type": "logic-directional-movement"
},{
"type": "render-debug"
}]
}
For a full list of key mappings check out Handler-Controller-Key-List.
#Mouse and Touch Controls Keyboard controls are somewhat easy to set up, but mouse and touch controls are a little more complicated, primarily due to interfacing between render components that trigger the input events and the control handler on the receiving side. There are two ways to go about this depending on the game design. One uses CreateJS render components and the other uses DOM elements and events.
##CreateJS Render Components Starting with a simple example, although admittedly not very useful, we can cause a touch event on the hero to make him walk right. To get this set up, we will need to set up some additional settings on another component on our hero: Render-Debug. These settings are identical for other render components like Render-Sprite.
We need to give the render-debug
a new property titled 'acceptInput' and set its child property 'click' to true (this enables both click and touch events). Once this is set the rendering of the hero on the screen becomes clickable (and touchable). This causes the debug-render
component to trigger 'mouseup' and 'mousedown' events on the entity. The entity-controller
component is already set up to listen for these types of events and internally maps them to a standard controller event message specifying the mouse button. Using these events we can update our entity definition like this:
{
"id": "hero",
"components":[{
"type": "entity-controller",
"controlMap": {
"key:left-arrow": "go-left",
"key:right-arrow": "go-right",
"mouse-left-button": "go-right"
}
},{
"type": "logic-directional-movement"
},{
"type": "render-debug",
"acceptInput": {"click": true}
}]
}
##DOM Element Entities
Clicking the hero is a little odd as a controller, so we need to take this a step further. Let's separate the click/touch input from the hero and make it another entity: an on-screen button that the player can click to make the hero go right. In fact, we can create two: one for going left and another for going right. The "button-right" entity might look something like this:
{
"id": "button-right",
"components":[{
"type": "dom-element",
"className": "game-button-right",
"onmousedown": "start-move",
"ontouchstart": "start-move",
"onmouseup": "stop-move",
"ontouchend": "stop-move",
"ontouchcancel": "stop-move"
},{
"type": "broadcast-events",
"events":{
"start-move": "button-right:down",
"stop-move": "button-right:up"
}
}]
}
This entity is comprised of two components, a Dom-Element component that creates a DOM element on the screen and a Broadcast-Events component that transmits entity messages to the rest of the game (including the hero entity). The first step is to tell the DOM element what events to trigger on the entity. For this component, we can map DOM events with the messages that should be triggered. In this case, "onmousedown" and "ontouchstart" both trigger "start-move" on the entity and "onmouseup", "ontouchend", and "ontouchcancel" trigger "stop-move". Once input events are triggered on the entity, we want the messages to make their way to the hero using the broadcast-events
component which takes local entity messages and triggers them as new messages at another scope, in this case to the entire scene. The "start-move" message triggers "button-right:down" on the scene and "stop-move" triggers "button-right:up" on the scene.
So now that the input entity is triggering messages, how does the hero listen for these? This is where the Handler-Controller comes in once again. It recognizes ":up" and ":down" messages triggered at the scene level and re-transmits them to all entities in its layer that have an Entity-Controller, including the hero entity. So the updated hero entity now looks like this (assuming we've also created a 'button-left' entity and removed "acceptInput" from the render component):
{
"id": "hero",
"components":[{
"type": "entity-controller",
"controlMap": {
"key:left-arrow": "go-left",
"key:right-arrow": "go-right",
"button-left": "go-left",
"button-right": "go-right"
}
},{
"type": "logic-directional-movement"
},{
"type": "render-debug"
}]
}
Note that in the above example, the messages used were arbitrarily selected ("button-right" and "stop-move"): you can use descriptive messages unique to the input actions your entities require, as long as they are unique from other messages on the entity.
#Conclusion Now the hero entity can walk left and right. To add another direction or action, use the same process as above and simply change the messages.
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.