Hi there. I’ve been working on a project. I have a restaurant/cafe type setting, and employees and machines that I can spawn into the game. The customers are spawned at different intervals.
One of the features is being able to select an employee, and order it to use a machine, such as an espresso machine (labeled as coffee maker). fohZone
zone object is what I’m using to handle the input. (clicking on the employee)
Heres the code I am using for the employee:
export class FOHEntity extends Entity {
constructor(scene, x, y, texture) {
super(scene, x, y, texture)
this.scene = scene
this.setOrigin(0.16, 0.5);
this.setFrame(7)
this.finder = new EasyStar.js()
this.setupFinder()
this.name = null
this.hasReachedCashRegister = false
this.hasReachedCoffeeMaker = false
this.idNumber = 0
this.crIDInUse = 0
this.randomMakeCoffeeSpeedValue = 0
this.coffeeID = null
this.isMakingCoffee = false
this.markerSelect = this.scene.add.sprite(0, 0, "marker").setFrame(2)
this.markerSelect.setVisible(false)
this.markerSelect.setDepth(9000)
this.fohStateMachine = new StateMachine('followPointer', {
followPointer: new FOHFollowPointerState(),
idle: new FOHIdleState(),
cashRegister: new FOHHandleCashRegisterState(),
coffeeMaker: new FOHHandleCoffeeMakerState(),
makeCoffee: new FOHMakeCoffeeState(),
moveToPlace: new FOHMoveToPlaceState(),
placeCoffee: new FOHPlaceCoffeeState()
}, [this, scene])
this.fohZone = this.scene.add.zone(0, 0, 16, 20);
this.fohZone.setOrigin(0, 0)
this.fohZone.setInteractive()
this.fohZone.name = "FohZone"
this.scene.physics.world.enable(this.fohZone);
this.fohZone.idNumber = this.idNumber
this.isSelected = false
this.cmIDInUse = 0
this.debugScene = this.scene.scene.get("DebugScene")
// Handling employee selection
this.fohZone.on("pointerover", () => {
this.scene.input.off("pointerdown")
this.scene.input.on("pointerdown", (pointer, obj) => {
this.isSelected = true
})
})
this.fohZone.on("pointerout", () => {
this.scene.input.off("pointerdown")
this.scene.input.on("pointerdown", () => {
for (let index = 0; index < this.scene.fohEntities.getChildren().length; index++) {
this.scene.fohEntities.getChildren()[index].isSelected = false
}
})
})
}
setupFinder() {
// We create the 2D array representing all the tiles of our map
let grid = [];
for (let y = 0; y < this.scene.map.height; y++) {
let col = [];
for (let x = 0; x < this.scene.map.width; x++) {
// In each cell we store the ID of the tile, which corresponds
// to its index in the tileset of the map ("ID" field in Tiled)
col.push(this.getTileID(x, y));
}
grid.push(col);
}
this.finder.setGrid(grid);
let tileset = this.scene.map.tilesets[0]
let properties = tileset.tileProperties
let acceptableTiles = []
// // We need to list all the tile IDs that can be walked on. Let's iterate over all of them
// // and see what properties have been entered in Tiled.
for (let i = tileset.firstgid - 1; i < this.scene.tiles.total; i++) { // firstgid and total are fields from Tiled that indicate the range of IDs that the tiles can take in that tileset
if (!properties.hasOwnProperty(i)) {
// If there is no property indicated at all, it means it's a walkable tile
acceptableTiles.push(i + 1);
continue;
}
if (!properties[i].collide) acceptableTiles.push(i + 1);
if (properties[i].cost) this.finder.setTileCost(i + 1, properties[i].cost); // If there is a cost attached to the tile, let's register it
}
this.finder.setAcceptableTiles(acceptableTiles)
}
handleMove(a, b) {
let x = a
let y = b
let tileXY = this.scene.map.tileToWorldXY(x, y)
let toX = Math.floor(tileXY.x / 16);
let toY = Math.floor(tileXY.y / 16);
let fromX = Math.floor(this.getEntity().x / 16);
let fromY = Math.floor(this.getEntity().y / 16);
let currentThis = this
this.finder.findPath(fromX, fromY, toX, toY, function (path) {
if (path === null) {
} else {
currentThis.moveCharacter(path)
}
});
this.finder.calculate(); // don't forget, otherwise nothing happens
}
moveCharacter(path) {
let tweens = []
for (let i = 0; i < path.length - 1; i++) {
let ex = path[i + 1].x
let ey = path[i + 1].y
tweens.push({
targets: this,
x: { value: ex * this.scene.map.tileWidth, duration: 200 },
y: { value: ey * this.scene.map.tileHeight, duration: 200 }
})
}
this.scene.tweens.timeline({
tweens: tweens
})
}
getTileID(x, y) {
let tile = this.scene.map.getTileAt(x, y, true, "groundLayer")
return tile.index
}
getEntity() {
return this
}
update() {
// handling coffee selection
if (this.isSelected == true) {
this.markerSelect.setVisible(true)
for (let index = 0; index < this.scene.coffeeMakerEntities.getChildren().length; index++) {
this.scene.coffeeMakerEntities.getChildren()[index].configZone.off("pointerdown")
this.scene.coffeeMakerEntities.getChildren()[index].configZone.on("pointerdown", () => {
console.log("use coffee maker")
let obj = { index: index }
this.fohStateMachine.transition("coffeeMaker", obj)
})
}
// for (let index = 0; index < this.scene.cashRegisterEntities.getChildren().length; index++) {
// this.scene.cashRegisterEntities.getChildren()[index].zone.off("pointerdown")
// this.scene.cashRegisterEntities.getChildren()[index].zone.on("pointerdown", () => {
// console.log("use")
// let obj = { index: index }
// this.fohStateMachine.transition("cashRegister", obj)
// })
// }
} else {
for (let index = 0; index < this.scene.coffeeMakerEntities.getChildren().length; index++) {
this.scene.coffeeMakerEntities.getChildren()[index].configZone.off("pointerdown")
this.scene.coffeeMakerEntities.getChildren()[index].configZone.on("pointerdown", () => {
console.log("config")
let obj = { gameScene: this.scene, coffeeIndex: index }
this.scene.scene.launch("CoffeeMenuScene", obj)
})
}
this.markerSelect.setVisible(false)
}
this.fohZone.x = this.x
this.fohZone.y = this.y - 8
this.markerSelect.x = this.x + 8
this.markerSelect.y = this.y
this.fohStateMachine.step()
}
}
The entity class for the employee has a isSelected boolean, and is changed depending if the pointerout or pointerdown is triggered.
Then I have another listener with the coffee machine in the update function. You can click on the coffee maker, which result will depend on if you have selected an employee. Clicking on the machine without an employee selected will bring up a menu for that coffee machine.
So far, this works for one employee, but does not work when more than one employee has spawned. Only the newest employee that has spawned will continue to work properly, the other employees will load the menu and use the coffee machine at the same time, which is incorrect behaviour.
Something is faulty with the logic I’m using, and I’m having difficulty solving this. It can be rather confusing. Heh.
I’m an intermediate amateur at best when it comes to coding and js, so there are some concepts that I have not being able to fully grasp yet, but I hope to in the near future. I would much appreciate any suggestions or ideas.
I’m going to upload my code to github some point soon, so people can check it out if they want.
EDIT: Oops made some mistake posting this twice
Thanks again.