Phaser World Issue 34
Another week has passed, and Phaser 2.4.9 has grown in strength yet again. The amount of hours I've spent this week, and the volume of commits, shows just how significantly it has been developing. Despite being just a point release it feels to me like a proper major version. The end result of all this hard work is ...
2.4.9 Release Candidate 4 is now ready for testing.
Just like last week: I have pushed up a complete release to the GitHub dev branch, including the latest doc files, TypeScript defs and all build files. If you use TypeScript I'd especially welcome your tests.
There is a forum thread you can leave me messages. Or just open new GitHub Issues, I don't mind which.
As always, please take a moment to scan through the Change Log. I know it's quite daunting, but I try to be as detailed as possible, so you can get a real sense as to what has actually changed (and which awesome community member contributed towards the change, if any :)
New Input Features
The 2.4.9 release includes some significant new features in the Input Manager. Here are a few worth singling out for special mention:
Sprite Drag enhancements: Sometimes it's really useful to not start a drag event until the mouse has moved a certain distance. You can now specify this via a "dragDistanceThreshold" property. It's a distance (in pixels) that the mouse has to 'drag' the Sprite for, before it's considered a valid drag. This is really useful to help distinguish between clicks (accidental, or otherwise) and actual drags.
There is also a "dragTimeThreshold" - which works in the same way, but allows you to specify a time value instead. So the mouse must be held down for the time given before a drag event is considered as having started.
The Input Handler also has a new property "downPoint", which stores the position the pointer was at when it was pressed down on the Sprite.
Both of these are very useful if you're building games aimed at young children, who perhaps have less defined motor skills (and need a more forgiving interface to their games).
You can also control what happens with the drag Input events: "dragStopBlocksInputUp" is a new boolean. If 'false' (the default, to keep it backward compatible), then both the onInputUp and onDragStop events are dispatched, when a Sprite stops being dragged. If 'true' then onInputUp is skilled.
Group Input Events
Set "inputEnableChildren" to true on a Group, and all new children added to, or created by it, will be enabled for input automatically.
However there's also a new reverse flag: "ignoreChildInput" - this is available on any Group, Sprite, or object that has children. If you set it to 'true' then all immediate children of that object will not be considered as valid for Input. This allows you to ignore input events for all children in a Group, without having to do any iteration, or deep-flag setting.
Groups now also have 4 new signals you can listen to: onChildInputDown, onChildInputUp, onChildInputOver and onChildInputOut. They are dispatched whenever any immediate child of the Group emits one of those events. This allows you to bind just one function to a Group signal, that works across all children in the Group, rather than binding it to the input event for every single child. It's more efficient (uses less memory), and lets you keep your code cleaner.
Custom Interactive Candidate Handler
This is a really advanced feature that I expect most of you won't need. But for those of you who do, it's a real lifeline :)
Pointer.interactiveCandidates is a new Array that is erased and re-populated every time the Pointer is updated. It contains references to all of the Game Objects that were considered as being valid for processing by this Pointer, during the most recent update. To be valid they must have suitable a `priorityID`, be Input enabled, be visible and actually have the Pointer over them. You can check the contents of this array in events such as `onInputDown`, but beware: it is reset every update.
Combined with this new array is Input.setInteractiveCandidateHandler. This allows you to add a callback that is fired every time Pointer.processInteractiveObjects is called. The purpose of processInteractiveObjects is to work out which Game Object the Pointer is going to interact with.
It works by polling all of the valid game objects, and then slowly discounting those that don't meet the criteria (i.e. they aren't under the Pointer, are disabled, invisible, etc). Eventually a short-list of 'candidates' is created. These are all of the Game Objects which are valid for input and overlap with the Pointer. At this point Phaser will then pick it's favorite candidate, based on it's location in the display list (the higher, the better), and its priority ID value.
However if you need fine-grained control over which of the items is selected then you can use this callback to do so. The callback will be sent 3 parameters: 1) A reference to the Phaser.Pointer object that is processing the Items. 2) An array containing all potential interactive candidates. This is an array of `InputHandler` objects, not Sprites. 3) The current 'favorite' candidate, based on its priorityID and position in the display list. Your callback MUST return one of the candidates sent to it (or null).
This will let you craft extremely complex UI input handling features in your games, easily letting you create customised input hierarchies that aren't in any way bound to the display list.
These are just a few features in 2.4.9! I urge you to check out the Change Log to see the rest.
Another week has passed, and Phaser 2.4.9 has grown in strength yet again. The amount of hours I've spent this week, and the volume of commits, shows just how significantly it has been developing. Despite being just a point release it feels to me like a proper major version. The end result of all this hard work is ...
2.4.9 Release Candidate 4 is now ready for testing.
Just like last week: I have pushed up a complete release to the GitHub dev branch, including the latest doc files, TypeScript defs and all build files. If you use TypeScript I'd especially welcome your tests.
There is a forum thread you can leave me messages. Or just open new GitHub Issues, I don't mind which.
As always, please take a moment to scan through the Change Log. I know it's quite daunting, but I try to be as detailed as possible, so you can get a real sense as to what has actually changed (and which awesome community member contributed towards the change, if any :)
New Input Features
The 2.4.9 release includes some significant new features in the Input Manager. Here are a few worth singling out for special mention:
Sprite Drag enhancements: Sometimes it's really useful to not start a drag event until the mouse has moved a certain distance. You can now specify this via a "dragDistanceThreshold" property. It's a distance (in pixels) that the mouse has to 'drag' the Sprite for, before it's considered a valid drag. This is really useful to help distinguish between clicks (accidental, or otherwise) and actual drags.
There is also a "dragTimeThreshold" - which works in the same way, but allows you to specify a time value instead. So the mouse must be held down for the time given before a drag event is considered as having started.
The Input Handler also has a new property "downPoint", which stores the position the pointer was at when it was pressed down on the Sprite.
Both of these are very useful if you're building games aimed at young children, who perhaps have less defined motor skills (and need a more forgiving interface to their games).
You can also control what happens with the drag Input events: "dragStopBlocksInputUp" is a new boolean. If 'false' (the default, to keep it backward compatible), then both the onInputUp and onDragStop events are dispatched, when a Sprite stops being dragged. If 'true' then onInputUp is skilled.
Group Input Events
Set "inputEnableChildren" to true on a Group, and all new children added to, or created by it, will be enabled for input automatically.
However there's also a new reverse flag: "ignoreChildInput" - this is available on any Group, Sprite, or object that has children. If you set it to 'true' then all immediate children of that object will not be considered as valid for Input. This allows you to ignore input events for all children in a Group, without having to do any iteration, or deep-flag setting.
Groups now also have 4 new signals you can listen to: onChildInputDown, onChildInputUp, onChildInputOver and onChildInputOut. They are dispatched whenever any immediate child of the Group emits one of those events. This allows you to bind just one function to a Group signal, that works across all children in the Group, rather than binding it to the input event for every single child. It's more efficient (uses less memory), and lets you keep your code cleaner.
Custom Interactive Candidate Handler
This is a really advanced feature that I expect most of you won't need. But for those of you who do, it's a real lifeline :)
Pointer.interactiveCandidates is a new Array that is erased and re-populated every time the Pointer is updated. It contains references to all of the Game Objects that were considered as being valid for processing by this Pointer, during the most recent update. To be valid they must have suitable a `priorityID`, be Input enabled, be visible and actually have the Pointer over them. You can check the contents of this array in events such as `onInputDown`, but beware: it is reset every update.
Combined with this new array is Input.setInteractiveCandidateHandler. This allows you to add a callback that is fired every time Pointer.processInteractiveObjects is called. The purpose of processInteractiveObjects is to work out which Game Object the Pointer is going to interact with.
It works by polling all of the valid game objects, and then slowly discounting those that don't meet the criteria (i.e. they aren't under the Pointer, are disabled, invisible, etc). Eventually a short-list of 'candidates' is created. These are all of the Game Objects which are valid for input and overlap with the Pointer. At this point Phaser will then pick it's favorite candidate, based on it's location in the display list (the higher, the better), and its priority ID value.
However if you need fine-grained control over which of the items is selected then you can use this callback to do so. The callback will be sent 3 parameters: 1) A reference to the Phaser.Pointer object that is processing the Items. 2) An array containing all potential interactive candidates. This is an array of `InputHandler` objects, not Sprites. 3) The current 'favorite' candidate, based on its priorityID and position in the display list. Your callback MUST return one of the candidates sent to it (or null).
This will let you craft extremely complex UI input handling features in your games, easily letting you create customised input hierarchies that aren't in any way bound to the display list.
These are just a few features in 2.4.9! I urge you to check out the Change Log to see the rest.