Logo

dev-resources.site

for different kinds of informations.

Phaser: Loading assets in a saner way

Published at
4/19/2020
Categories
gamedev
devlog
phaser
showdev
Author
Nรบria
Categories
4 categories in total
gamedev
open
devlog
open
phaser
open
showdev
open
Phaser: Loading assets in a saner way

It's been some time since I talked about the code of the game, so I thought I'd share some of the changes I've made to make my life easier, in the shape of short posts. Today's turn isโ€ฆ

Loading Assets

As you may know, to add an asset to a Phaser scene, you need to call a load function with a key and the asset path as parameters. If the asset is a sprite, you also need to pass the frame width and height.

this.load.spritesheet('enemy', `/images/enemy.png`, {
  frameWidth: 50,
  frameHeight: 160
})

As you can imagine, when you have a lot of sprites, the preloading of all the assets becomes very verbose, and if you use the same sprite in different scenes, having the width and height hardcoded is tiresome and a potential source of bugs (if you change the size of the sprite, it's likely you forget to update it everywhere).

So the first step to improve this is to move all this hardcoded data to a constants.ts file. We've solved an issue but it's still quite verbose. This is how a scene preload function looked like at a certain point:

public preload() {
  this.load.audio(AUDIO.FIRE.KEY, `/sound/${AUDIO.FIRE.FILE}`)
  this.load.audio(AUDIO.STATIC.KEY, `/sound/${AUDIO.STATIC.FILE}`)
  this.load.audio(AUDIO.DROP.KEY, `/sound/${AUDIO.DROP.FILE}`)
  this.load.audio(AUDIO.BANG.KEY, `/sound/${AUDIO.BANG.FILE}`)
  this.load.image(
    IMAGES.BUILDING_BG.KEY,
    `/images/${IMAGES.BUILDING_BG.FILE}`
  )
  this.load.image(
    IMAGES.BUILDING_BG_2.KEY,
    `/images/${IMAGES.BUILDING_BG_2.FILE}`
  )
  this.load.image(IMAGES.FLOOR.KEY, `/images/${IMAGES.FLOOR.FILE}`)
  this.load.image(IMAGES.LADDER.KEY, `/images/${IMAGES.LADDER.FILE}`)
  this.load.image(IMAGES.BOXES.KEY, `/images/${IMAGES.BOXES.FILE}`)
  this.load.image(IMAGES.BUCKET.KEY, `/images/${IMAGES.BUCKET.FILE}`)
  this.load.image(IMAGES.WOOD.KEY, `/images/${IMAGES.WOOD.FILE}`)
  this.load.image(IMAGES.CLOTH.KEY, `/images/${IMAGES.CLOTH.FILE}`)
  this.load.image(IMAGES.DROP.KEY, `/images/${IMAGES.DROP.FILE}`)
  this.load.image(IMAGES.ROCK.KEY, `/images/${IMAGES.ROCK.FILE}`)
  this.load.image(IMAGES.METALBOX.KEY, `/images/${IMAGES.METALBOX.FILE}`)
  this.load.spritesheet(
    IMAGES.ANTENNA.KEY,
    `/images/${IMAGES.ANTENNA.FILE}`,
    {
      frameWidth: 160,
      frameHeight: 504
    }
  )
  this.load.spritesheet(
    IMAGES.FIREPIT.KEY,
    `/images/${IMAGES.FIREPIT.FILE}`,
    {
      frameWidth: 84,
      frameHeight: 60
    }
  )
}

I have a BaseScene with some common methods that all scenes inherit, to I created a loadAudio, loadImage and loadSprite functions there that receive the sprite constant as a parameter:

public loadSprite(SPRITE: SpriteAsset) {
  this.load.spritesheet(SPRITE.KEY, `/images/${SPRITE.FILE}`, {
    frameWidth: SPRITE.WIDTH,
    frameHeight: SPRITE.HEIGHT
  })
}

So the preload function ended up looking like this. It's actually loading more assets than before, but it's way easier to read:

public preload() {
  // Preload audio
  this.loadAudio(AUDIO.FIRE)
  this.loadAudio(AUDIO.STATIC)
  this.loadAudio(AUDIO.DROP)
  this.loadAudio(AUDIO.BANG)

  // Preload images
  this.loadImage(IMAGES.BUILDING_BG)
  this.loadImage(IMAGES.BUILDING_BG_2)
  this.loadImage(IMAGES.BUILDING_NIGHT_BG)
  this.loadImage(IMAGES.BUILDING_NIGHT_BG_2)
  this.loadImage(IMAGES.FLOOR)
  this.loadImage(IMAGES.WOOD)
  this.loadImage(IMAGES.CLOTH)
  this.loadImage(IMAGES.DROP)
  this.loadImage(IMAGES.ROCK)

  // Preload sprites
  this.loadSprite(SPRITES.METALBOX)
  this.loadSprite(SPRITES.LADDER)
  this.loadSprite(SPRITES.BUCKET)
  this.loadSprite(SPRITES.BOXES)
  this.loadSprite(SPRITES.ANTENNA)
  this.loadSprite(SPRITES.FIREPIT)
  this.loadSprite(SPRITES.BUGGY)
  this.loadSprite(SPRITES.STRANGER)
}

There's still room for improvement, for example I could have all the audio, images and sprites a scene needs in a constant, and load them all in a single call. But for now it's more than enough to make the code a bit more readable!

Featured ones: