Wednesday, August 26, 2015

Pick a Pack of Assets - for Phaser

If you don't care for asset packs,
how about fanny packs? No? Okay.
I performed one more refactor of my Frog Soccer game. In preload, I used to have lots of individual calls to load different types of assets - static images, sprite sheets, audio, and maps. While looking for a way to improve this, I discovered that Phaser supports loading asset packs.

An asset pack is just a JSON-format file that describes sets of game assets. This is then given to the Loader which parses it and then performs all the loads. It is functionally equivalent to putting the individual game.load.image, game.load.spritesheet, game.load.audio, etc. calls in preload. Loading from a pack is just more convenient.

To use it, you first have to make a pack file. It is a JSON file, and that means it must be valid JSON. Unlike in JavaScript where you can leave off the quotes around the field names, a real JSON-format file should always quote every string.

// this is NOT a valid JSON file:
{
    main: [
        {
            type: "image",
            key: "goal",
            url: "assets/images/goal.png"
        }
    ]
}

// but this IS a valid JSON file:
{
    "main": [
        {
            "type": "image",
            "key": "goal",
            "url": "assets/images/goal.png"
        }
    ]
}

The format of the pack files is detailed in the example file located in the Phaser source code: assetPack.json. It supports arbitrary grouping of assets so that you can make sets of assets for different levels of your game, for example. In my game, there is only one "level" so I just put everything in array referenced by the name main.

{
    "main": [
        {
            "type": "image",
            "key": "goal",
            "url": "assets/images/goal.png"
        },
        {
            "type": "image",
            "key": "goal2",
            "url": "assets/images/goal2.png"
        },
        {
            "type": "image",
            "key": "net",
            "url": "assets/images/net.png"
        },
        {
            "type": "image",
            "key": "net2",
            "url": "assets/images/net2.png"
        },
        {
            "type": "image",
            "key": "tiles",
            "url": "assets/images/field-tiles.png"
        },
        {
            "type": "spritesheet",
            "key": "ball",
            "url": "assets/sprites/ball.png",
            "frameWidth": 45,
            "frameHeight": 45
        },
        {
            "type": "spritesheet",
            "key": "frog",
            "url": "assets/sprites/frog.png",
            "frameWidth": 79,
            "frameHeight": 60
        },
        {
            "type": "spritesheet",
            "key": "frog2",
            "url": "assets/sprites/frog2.png",
            "frameWidth": 79,
            "frameHeight": 60
        },
        {
            "type": "audio",
            "key": "whistle",
            "urls": ["assets/audio/whistle.mp3"]
        },
        {
            "type": "tilemap",
            "key": "map",
            "url": "assets/ground.json",
            "data": null,
            "format": "TILED_JSON"
        }
    ]
}

The basic format is that you specify one or more fields consisting of arrays of objects. I have defined one named main. The objects inside the array represent the individual assets that you want to load. Each type has slightly different fields which essentially map to the fields of each type's loader function. They are all listed in the example file I mentioned earlier if you want details . One interesting thing to note is how audio assets use an array of URLs instead of a single one. This is because you often specify a single audio asset in multiple formats to support all web browsers. The rest of the stuff in the file is fairly self-explanatory.

With this in place, my preload method just looks like this:

function preload() {

    game.load.pack("main", "assets/pack.json");

}

Really, that's it. The whole thing. I really like this method. I also really like frogs. Frogs being chased by angry ducks. That's not weird.

Amphibian.com comic for 26 August 2015