Hi there.
So I’ve been working on a project, and have become stumped due to a problem.
import { Player } from '../../classes/entities/Player.js'
import { Zone } from '../../classes/entities/Zone.js'
import { NPCMinotaur } from '../../classes/entities/NPCMinotaur.js'
import { Item } from '../../classes/entities/Item.js'
export class GameScene extends Phaser.Scene {
constructor() {
super({ key: 'GameScene', active: false })
}
init(data) {
this.sceneName = 'GameScene'
this.posX = data.posX
this.posY = data.posY
}
create() {
let selectData = { mainScene: this}
this.scene.launch("ToolInventoryScene", selectData)
this.scene.launch("ItemInventoryScene", selectData)
this.menuKeys = this.input.keyboard.addKeys("TAB");
this.players = this.physics.add.group({
classType: Player,
runChildUpdate: true,
})
this.zones = this.physics.add.group({
classType: Zone,
runChildUpdate: true
})
this.npcMinotaurs = this.physics.add.group({
classType: NPCMinotaur,
runChildUpdate: true,
})
this.droppedItems = this.physics.add.group({
classType: Item,
runChildUpdate: true
})
this.map2 = this.make.tilemap({ key: 'map-1-1' })
let tiles2 = this.map2.addTilesetImage('tileset-extruded', 'tiles', 16, 16, 2, 2);
this.layer1 = this.map2.createLayer('groundLayer', tiles2, 0, 0);
this.layer2 = this.map2.createLayer('collideLayer', tiles2, 0, 0);
this.npcMinotaursLayer = this.map2.getObjectLayer('npcs')
this.zonesLayer = this.map2.getObjectLayer('zones')
this.players.get(this.posX, this.posY, "adventurer")
this.npcMinotaursLayer.objects.forEach((obj) => {
this.npcMinotaurs.get(obj.x, obj.y, 'minotaur').setDepth(100)
})
this.zonesLayer.objects.forEach((obj) => {
this.zones.get(obj.x + obj.width / 2, obj.y + obj.height / 2, obj.width, obj.height)
})
this.dungeonOneScene = this.scene.get("DungeonOne")
this.physics.add.overlap(this.zones.getChildren()[0], this.players.getChildren()[0], () => {
let data = {
players: this.players,
posX: 57,
posY: 77,
playerHealth: this.players.getChildren()[0].health,
playerInventory: this.players.getChildren()[0].playerInventory,
toolInventory: this.players.getChildren()[0].toolInventory,
itemInventory: this.players.getChildren()[0].itemInventory,
prevScene: this,
}
this.scene.wake('DungeonOne', data)
this.scene.sleep()
})
let data = { players: this.players, scene: this}
this.scene.launch('GameUIScene', data)
}
setPlayerPos(x, y) {
this.players.getChildren()[0].x = x
this.players.getChildren()[0].y = y
}
setPlayerHealth(value) {
this.players.getChildren()[0].health = value
}
dropItem(x, y, randomNumber) {
if (randomNumber == 0) {
this.droppedItems.create(x, y, 'item').setInteractive()
.inventory.addItem({ name: 'Healing Potion', quantity: 1 })
}
if (randomNumber == 1) {
this.droppedItems.create(x, y, 'item')
.setInteractive()
.inventory.addItem({ name: 'Healing Potion', quantity: 2 })
}
if (randomNumber == 2) {
this.droppedItems.create(x, y, 'item').setInteractive()
.inventory.addItem({ name: "Apple", quantity: 3 })
}
if (randomNumber == 3) {
this.droppedItems.create(x, y, 'item').setInteractive()
}
if (randomNumber == 4) {
this.droppedItems.create(x, y, 'item').setInteractive()
.inventory.addItem({ name: "Flame Staff", quantity: 1 })
}
if (randomNumber == 5) {
this.droppedItems.create(x, y, 'item').setInteractive()
.inventory.addItem({ name: "Healing Potion", quantity: 2 })
}
if (randomNumber == 6) {
this.droppedItems.create(x, y, 'item').setInteractive()
.inventory.items[{ name: 'test', quantity: 2 }, { name: 'qweqw', quantity: 2 }]
}
}
update() {
let player = this.players.getChildren()[0]
console.log(player.x, player.y)
this.cameras.main.startFollow(player, false, 0.08, 0.08)
this.cameras.main.setZoom(2.8);
if (Phaser.Input.Keyboard.JustDown(this.menuKeys.TAB)) {
let data = { playerInventory: this.players.getChildren()[0].playerInventory, player: this.players.getChildren()[0], scene: this };
this.scene.pause()
this.scene.launch("InGameMenuScene", data);
}
}
}
import { Player } from '../../classes/entities/Player.js'
import { Zone } from '../../classes/entities/Zone.js'
import { NPCMinotaur } from '../../classes/entities/NPCMinotaur.js'
import { Item } from '../../classes/entities/Item.js'
export class DungeonOne extends Phaser.Scene {
constructor() {
super({ key: 'DungeonOne', active: false })
}
init(data) {
this.sceneName = 'DungeonOne'
this.playerInventory = data.playerInventory
this.toolInventory = data.toolInventory
this.itemInventory = data.itemInventory
}
create(data) {
let selectData = { mainScene: this}
this.scene.launch("ToolInventoryScene", selectData)
this.scene.launch("ItemInventoryScene", selectData)
this.menuKeys = this.input.keyboard.addKeys("TAB");
this.players = this.physics.add.group({
classType: Player,
runChildUpdate: true,
})
this.zones = this.physics.add.group({
classType: Zone,
runChildUpdate: true
})
this.npcMinotaurs = this.physics.add.group({
classType: NPCMinotaur,
runChildUpdate: true,
})
this.droppedItems = this.physics.add.group({
classType: Item,
runChildUpdate: true
})
console.log(this.npcMinotaurs, this.npcs)
this.map2 = this.make.tilemap({ key: 'map-1-2' })
let tiles2 = this.map2.addTilesetImage('tileset-extruded', 'tiles', 16, 16, 2, 2);
this.layer1 = this.map2.createLayer('groundLayer', tiles2, 0, 0);
this.layer2 = this.map2.createLayer('collideLayer', tiles2, 0, 0);
this.npcMinotaursLayer = this.map2.getObjectLayer('npcs')
this.zonesLayer = this.map2.getObjectLayer('zones')
this.zonesLayer.objects.forEach((obj) => {
this.zones.get(obj.x + obj.width / 2, obj.y + obj.height / 2, obj.width, obj.height)
})
this.npcMinotaursLayer.objects.forEach((obj) => {
this.npcMinotaurs.get(obj.x, obj.y, 'minotaur').setDepth(100)
})
this.players.get(this.posX, this.posY, "adventurer")
this.physics.add.overlap(this.zones.getChildren()[0], this.players.getChildren()[0], () => {
let data = {
players: this.players,
posX: 318,
posY: 142,
npcs: this.npcs,
playerHealth: this.players.getChildren()[0].health,
playerInventory: this.players.getChildren()[0].playerInventory,
toolInventory: this.players.getChildren()[0].toolInventory,
itemInventory: this.players.getChildren()[0].itemInventory,
prevScene: this,
}
this.scene.wake('GameScene', data)
this.scene.sleep()
})
}
setPlayerPos(x, y) {
this.players.getChildren()[0].x = x
this.players.getChildren()[0].y = y
}
setPlayerHealth(value) {
this.players.getChildren()[0].health = value
}
dropItem(x, y, randomNumber) {
// console.log(npc)
// npc.npcStateMachine.transition("dead")
if (randomNumber == 0) {
this.droppedItems.create(x, y, 'item').setInteractive()
.inventory.addItem({ name: 'Healing Potion', quantity: 1 })
}
if (randomNumber == 1) {
this.droppedItems.create(x, y, 'item')
.setInteractive()
.inventory.addItem({ name: 'Healing Potion', quantity: 2 })
}
if (randomNumber == 2) {
this.droppedItems.create(x, y, 'item').setInteractive()
.inventory.addItem({ name: "Apple", quantity: 3 })
}
if (randomNumber == 3) {
this.droppedItems.create(x, y, 'item').setInteractive()
}
if (randomNumber == 4) {
this.droppedItems.create(x, y, 'item').setInteractive()
.inventory.addItem({ name: "Flame Staff", quantity: 1 })
}
if (randomNumber == 5) {
this.droppedItems.create(x, y, 'item').setInteractive()
.inventory.addItem({ name: "Healing Potion", quantity: 2 })
}
if (randomNumber == 6) {
this.droppedItems.create(x, y, 'item').setInteractive()
.inventory.items[{ name: 'test', quantity: 2 }, { name: 'qweqw', quantity: 2 }]
}
}
update() {
this.gameScene = this.scene.get("GameScene")
let player = this.players.getChildren()[0]
this.cameras.main.startFollow(player, false, 0.08, 0.08)
this.cameras.main.setZoom(2.8);
if (Phaser.Input.Keyboard.JustDown(this.menuKeys.TAB)) {
let data = { playerInventory: this.players.getChildren()[0].playerInventory, player: this.players.getChildren()[0], scene: this };
this.scene.pause()
this.scene.launch("InGameMenuScene", data);
}
}
}
I have seperate scenes for the UI, being launched via this.scene.launch inside the first scene (called MainGameScene).
The first scene displays the first tilemap, and once a zone is overlapped in the tilemap, the player is led into the next scene (called DungeonOneScene), which displays the second map.
I’m having problems making the UI work, some of this I’ll have to explain. It works fine in MainGameScene as I launch the UI Scene. Because of the way the code is being handled in the UI scenes, usage of the UI doesnt work. I’m sending current scene data into the UI scene as it is launched, and I want that scene data to change depending on what scene you’re currently in.
As it switches to the DungeonOneScene, the UI scene only receives the previous scenes data, and so therefore the UI doesnt work properly in the DungeonOneScene. Ideally I’d want the scene that is passed into the UI scene to chance depending on which scene you are in.
I tried to launch the UI scenes again inside the DungeonOneScene, hopefully to update to the scene the player is in, inside the DungeonOneScene but it doesnt work. Seems like you can only use the this.scene.launch() function once, if I’m not mistaken.
export class ItemInventoryScene extends Phaser.Scene {
constructor() {
super("ItemInventoryScene")
this.rows = 1
this.uiScale = 1.5
this.gridSpacing = 4
this.margin = 8
this._tileSize = 32
this.inventorySlots = []
}
preload() {
}
init(data) {
// the data being passed from the first scene (data.mainScene is the scene from its current scene the player is in )
this.mainScene = data.mainScene
this.inventory = this.mainScene.players.getChildren()[0].itemInventory
this.maxColumns = this.mainScene.players.getChildren()[0].itemInventory.maxColumns
this.maxRows = this.mainScene.players.getChildren()[0].itemInventory.maxRows
this.inventory.subscribe(() => this.refresh())
this.playerStateMachine = this.mainScene.players.getChildren()[0].playerStateMachine
console.log(this.dungeonOneScene)
this.items = {
"Long Sword": { frame: "sword.png" },
"Short Sword": { frame: "sword.png" },
"Firebolt": { frame: "fire.png" },
"Blank": { frame: "blank.png" },
"Healing Potion": { frame: "potion.png" },
"Mana Potion": { frame: "potion2.png" },
"Apple": { frame: "apple.png" }
}
}
get tileSize() {
return this._tileSize * this.uiScale
}
destroyInventorySlot(inventorySlot) {
if (inventorySlot.item) inventorySlot.item.destroy()
inventorySlot.destroy()
}
refresh() {
console.log("refresh")
this.inventorySlots.forEach(s => this.destroyInventorySlot(s))
this.inventorySlots = []
for (let index = 0; index < this.maxColumns * this.rows; index++) {
let x = this.margin + this.tileSize / 2 + (index % this.maxColumns) * (this.tileSize + this.gridSpacing) + 130
let y = this.margin + this.tileSize / 2 + 37
let inventorySlot = this.add.sprite(x, y, "items1", "panel.png")
inventorySlot.setScale(this.uiScale)
let item = this.inventory.getItem(index)
if (item) {
inventorySlot.item = this.add.sprite(inventorySlot.x, inventorySlot.y, "items1", this.items[item.name].frame)
inventorySlot.setInteractive()
}
this.inventorySlots.push(inventorySlot)
this.inventorySlots[index].tint = 0xfffff
}
}
handleSlotPressed(index) {
this.inventorySlots[index].tint = 0xffff00
let timer = this.time.delayedCall(100, () => {
this.inventorySlots[index].tint = 0xfffff
});
}
create() {
this.input.keyboard.on("keydown-E", () => {
this.inventory.selected = 0
})
this.input.keyboard.on("keydown-R", () => {
this.inventory.selected = 1
})
this.refresh()
}
}
So long story short, my goal is for the player to be able to transition from scene to another with each scene having its own tilemap, and ideally, be able to retain all the items in the UI, and retain the current states of the npcs and the players.
Initally, I was using the this.scene.start, meaning that each time you entered the next scene, the scene would start each time. This was fine until I realized the npcs would restart every time back to its beginning.
I changed the code, started the game scenes in preload, and put the scenes being unused to sleep, and used this.scene.wake to wake up the scenes once the zone is overlapped.
So, I’ve realized that this is getting increasingly complex, and am asking if anyone knows of any manageable ways to handle scenes with its own tilemaps, and launching UI scenes on top.
Apologies if this is unbearable to read or understand.
I plan to get a working example up tomorrow to help solve this problem.
If anyone has any suggestions, I’d very much appreciate it!
Thanks