DEV Community

Cover image for Promisifying Phaser
Núria
Núria

Posted on

4 1

Promisifying Phaser

Working on web development, promises are a basic tool I use every day, and I feel that the old days when everybody used callbacks are long gone. Except when I'm working with Phaser!

For example, at the start of the game, I want to move the camera around so the player gets a sense of their surroundings, and then start playing the game. Phaser cameras have a pan method to do that, and this method receives a callback which is called on every update. In order to wait and call another method once the effect has finished, you need to check if the progress has reached 1:

create() {
  this.cameras.main.pan(
    this.survivor.x,
    this.survivor.y,
    4000,
    'Linear',
    false,
    (_, progress) => {
      if (progress === 1) {
        this.cameras.main.startFollow(this.survivor)
        this.play()
      }
    }
  )
}

This approach might be useful if I want to do something while the pan is running, but most of the time I want to wait until it's done, and it's a bit tedious to keep writing the callback, not to mention if you want to chain multiple effects: you easily run into callback hell.

So, I decided to turn this kind of Phaser methods into promises:

cameraPan(x: number, y: number, time = 1000) {
  return new Promise((resolve) => {
    this.cameras.main.pan(x, y, time, 'Linear', false, (_, progress) => {
      if (progress === 1) {
        resolve()
      }
    })
  })
}

This way, thanks to async/await, the previous code looks much simpler and easier to understand:

async create() {
  await this.cameraPan(this.survivor.x, this.survivor.y, 4000)
  this.cameras.main.startFollow(this.survivor)
  this.start()
}

The improvement is even more obvious when you are using several camera effects, tweens, and other methods that would require callbacks. Imagine how this code would look without await:

async endScene() {
  this.cameras.main.stopFollow()
  await this.cameraFade('fadeIn')
  await this.cameraPan(0, 0, 4000)
  await this.createDialog("How strange to see northern lights so far down south.")
  await this.cameraPan(this.survivor.x, this.survivor.y, 4000)
  await this.cameraFade('fadeOut', 2000)
}

You can still use the original Phaser method at certain points when you need more control over the progress, but I've found this is a quick and easy way to make your Phaser games a bit more readable. Hope it helped!

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

Top comments (1)

Collapse
 
jeffjadulco profile image
Jeff Jadulco

Great! This also makes the game feel smoother because there will be fewer hiccups :)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay