Thanks! This is the API that I’ve come up with:
In the scene where I need the player to drop a certain item into a certain area I do this:
this.scene.get('Inventory').makeDropZoneForItem('ironBar', ironBarOutline, {
dragenter: () => {
ironBarOutline.setTintFill(0xffffff)
},
dragleave: () => {
ironBarOutline.setTintFill(0xffd700)
},
drop: () => {
this.scene.start('Scene01')
},
})
then the implementation in the Inventory
scene looks like this:
makeDropZoneForItem(itemId, sourceForDropZone, eventHandlers) {
const sourceCenter = sourceForDropZone.getCenter()
const zone = this.add.zone(sourceCenter.x, sourceCenter.y, sourceForDropZone.width, sourceForDropZone.height)
.setInteractive({dropZone: true})
.setData('itemId', itemId)
.setScale(1.3) // Make it easier to drop an item on the zone.
for (const [eventName, eventHandler] of Object.entries(eventHandlers)) {
const wrappedEventHandler = function(pointer, gameObject, dropZone) {
// The drop zone is coupled to a specific inventory item.
const gameObjectMatchesDropZone = gameObject.data.get('itemId') == itemId && dropZone.data &&
gameObject.data.get('itemId') == dropZone.data.get('itemId')
if (gameObjectMatchesDropZone) {
eventHandler(pointer, gameObject, dropZone)
}
}
this.input.on(eventName, wrappedEventHandler)
}
}
One thing this code doesn’t handle is the fact that sourceForDropZone
can be destroyed, because the scene changes on drop. Fortunately, handling this is quite straightforward:
makeDropZoneForItem(itemId, sourceForDropZone, eventHandlers) {
const sourceCenter = sourceForDropZone.getCenter()
const zone = this.add.zone(sourceCenter.x, sourceCenter.y, sourceForDropZone.width, sourceForDropZone.height)
.setInteractive({dropZone: true})
.setData('itemId', itemId)
.setScale(1.3) // Make it easier to drop an item on the zone.
for (const [eventName, eventHandler] of Object.entries(eventHandlers)) {
const wrappedEventHandler = function(pointer, gameObject, dropZone) {
// The drop zone is coupled to a specific inventory item.
const gameObjectMatchesDropZone = gameObject.data.get('itemId') == itemId && dropZone.data &&
gameObject.data.get('itemId') == dropZone.data.get('itemId')
if (gameObjectMatchesDropZone) {
eventHandler(pointer, gameObject, dropZone)
}
}
this.input.on(eventName, wrappedEventHandler)
+ sourceForDropZone.on('destroy', () => {
+ this.input.off(eventName, wrappedEventHandler)
+ })
}
+ sourceForDropZone.on('destroy', () => {
+ zone.destroy()
+ })
}
Is there anything I forgot about?