Hello there. I’m trying to create a menu system with sub-menus, with both interaction with the mouse and/or keyboard.
I’m having trouble managing how this would work without making spaghetti code with lots of booleans and such. I’ve seperated each draw that I make into its own class, such as a Window class and a Panel class that has interaction.
It all seems fine but my process doesnt seem as modular and reuseable as I would like it to be. I’ve come across a lot of problems, one being unable to seperate what my Z key does when the menu is loaded, as opposed to when you’re moving your player.
import { Window } from '../classes/Window.js'
import { Panel } from '../classes/Panel.js'
import { QuestMenu } from '../classes/QuestMenu.js'
export class InGameMenu {
constructor(scene) {
this.menuWindow = new Window(scene, 10, 10, 780, 90)
this.menuWindow.getGraphics().visible = false
this.questMenu = new QuestMenu(scene)
this.questMenu.clear()
this.isMenuOn = false
this.menuKeys = scene.input.keyboard.addKeys("P, Z")
// menu select
this.activeRect = null
this._this = scene
this.activeRect = 0
this.rectGroup = []
this.rects = [0, 1, 2, 3]
this.textContainer = ["Inventory", "Quests", "Info", "Exit"]
this.rects.forEach(index => {
this.rectGroup.push(new Panel(this._this, 120 + 140 * index, 20, 120, 70, this.textContainer[index], index))
})
for (let i = 0; i < this.rectGroup.length; i++) {
this.rectGroup[i].visible = false
this.rectGroup[i].getText().visible = false
}
// input set to increment selected rectangle
scene.input.keyboard.on('keydown', event => {
switch (event.key) {
case 'ArrowLeft':
this.activeRect -= 1
this._this.events.emit('CHANGE_BUTTON')
break;
case 'ArrowRight':
this.activeRect += 1
this._this.events.emit('CHANGE_BUTTON')
break;
}
})
scene.events.addListener('CHANGE_BUTTON', (payload) => {
if (this.activeRect > 3) {
this.activeRect = 0
}
if (this.activeRect < 0) {
this.activeRect += this.rects.length;
}
if (payload && typeof payload.setIndex !== 'undefined')
this.activeRect = payload.setIndex;
this.rectGroup.forEach((rect) => {
rect.setStyleActive(rect.index == this.activeRect % this.rects.length)
})
if (this.activeRect == 0) {
console.log("selected inventory")
}
})
}
update(player) {
if (this.isMenuOn == false) {
if (Phaser.Input.Keyboard.JustDown(this.menuKeys.P)) {
this.gamestate = "INGAMEMENU"
}
} else {
if (Phaser.Input.Keyboard.JustDown(this.menuKeys.P)) {
this.gamestate = "GAME"
}
}
this.menuKeys.Z.enabled = false
switch (this.gamestate) {
case "GAME":
this.isMenuOn = false
this.menuWindow.getGraphics().visible = false
for (let i = 0; i < this.rectGroup.length; i++) {
this.rectGroup[i].visible = false
this.rectGroup[i].getText().visible = false
}
player.expression = "MOVING"
this.menuKeys.Z.enabled = false
this.questMenu.clear()
break;
case "INGAMEMENU":
this.isMenuOn = true
this.menuWindow.getGraphics().visible = true
for (let i = 0; i < this.rectGroup.length; i++) {
this.rectGroup[i].visible = true
this.rectGroup[i].getText().visible = true
}
player.expression = "PAUSED"
this.menuKeys.Z.enabled = true
break;
case "ENTERDIALOGUEUI":
this.isMenuOn = false
break;
default:
}
// use handling for key Z
if (this.activeRect == 0) {
if (Phaser.Input.Keyboard.JustDown(this.menuKeys.Z)) {
console.log("pressed on 0");
this.questMenu.clear()
}
}
if (this.activeRect == 1) {
if (Phaser.Input.Keyboard.JustDown(this.menuKeys.Z)) {
console.log("pressed on 1");
this.questMenu.show()
}
}
if (this.activeRect == 2) {
if (Phaser.Input.Keyboard.JustDown(this.menuKeys.Z)) {
console.log("pressed on 2");
this.questMenu.clear()
}
}
}
}
I want to eventually create an inventory, with items, similar to a lot of rpg games. My initial thoughts was to create a menu system similar to early Final Fantasy games (FF6, 7, 8, 9) or atleast the bare bones of it.
If anyone can offer advice on to do something like this, I’d really appreciate it.