<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
  </head>
  <body>
    <div id="phaser-example"</div>
  </body>
</html>
html,
body {
  background-color:#d4d4d4;
  margin:0px;
  paddign:0px;
}
class MenuText extends Phaser.GameObjects.Text {
  normalStyle = {
    fontSize: 52,
    color: '#ffffff'
  }
  activeStyle = {
    fontSize: 52,
    color: '#ffff00'
  }
  isActive = false

  constructor(scene: Phaser.Scene, x: number, y: number, text: string, public index: number) {
    super(scene, x, y, text, {})
    scene.add.existing(this)

    this.setStyle(this.normalStyle)
      .setInteractive()
      .on('pointerover', () => scene.events.emit('CHANGE_BUTTON', { setIndex: index }))

    this.setStyleActive(index === 0)
  }

  setStyleActive(active: boolean) {
    if (this.isActive === active) return
    this.isActive = active
    this.setStyle(this.isActive ? this.activeStyle : this.normalStyle)
  }
}

class MainScene extends Phaser.Scene {
  constructor() {
    super({ key: 'MainScene' })
  }

  create() {
    let activeText = 0
    let textGroup: MenuText[] = []
    const texts = ['Text1', 'Text2', 'Text3', 'Text4', 'Text5']

    texts.forEach((text, index) => {
      textGroup.push(new MenuText(this, this.cameras.main.width / 2, 100 + 80 * index + 1, text, index).setOrigin(0.5))
    })

    this.input.keyboard.on('keydown', event => {
      switch (event.key) {
        case 'ArrowUp':
          activeText -= 1
          this.events.emit('CHANGE_BUTTON')
          break
        case 'ArrowDown':
          activeText += 1
          this.events.emit('CHANGE_BUTTON')
          break
      }
    })

    this.events.addListener('CHANGE_BUTTON', payload => {
      if (activeText < 0) activeText += texts.length

      if (payload && typeof payload.setIndex !== 'undefined') activeText = payload.setIndex

      textGroup.forEach(text => {
        text.setStyleActive(text.index === activeText % texts.length)
      })
    })
  }
}
  
const config = {
    type: Phaser.AUTO,
    parent: 'phaser-example',
    backgroundColor: '#000000',
    scale: {
      mode: Phaser.Scale.FIT,
      autoCenter: Phaser.Scale.CENTER_BOTH,
      width: 500,
      height: 600
    },
    scene: MainScene,
}

const game = new Phaser.Game(config)
View Compiled
Run Pen

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/phaser/3.16.2/phaser.min.js