DEV Community 👩‍💻👨‍💻

Tony Colston
Tony Colston

Posted on

data uri textures with Phaser3

Loading textures from Phaser3 using a data uri instead of an image file.

Be clear that this does not save space. Loading from a data uri requires that the data (the image) is encoded in a way that can fit nicely into ASCII text. In this case it is encoded in Base 64 which is larger than the original file.

Loading Image elements in Javascript is asynchronous. So you must wait for the Image to be ready.

I used Scenes to handle the loading versus the usage of the texture.

You will have a LoadingScene that will load the data-uri into the TextureManager then once that is done we will move to the next GameScene that will use the textures in Sprite objects.

The tricky bit is that I am listening to the events on the TextureManager for the scene for "textureloaded" events. I keep up with the number of events I get and use that to move on to the next Scene.

How did I know that? I looked in the source for Phaser3! This is the call for addBase64
https://github.com/photonstorm/phaser/blob/a2956176dd5d64ebb6c00a4ad12660f1e6c824eb/src/textures/TextureManager.js#L265

And you can see in that source once the Image is loaded two events are fired. I picked the "addtexture" event.

The source is down below for the main portion of the code


import { mystring } from "./ds.js";
import { mystring as mystring2 } from "./ds2.js";

class LoadingTexturesOnly extends Phaser.Scene {
    constructor() {
        super("loading");
    }
    preload() {
        let count = 0;

        // had to read phaser source to find this
        // when you get a addtexture event the texture
        // is done loading
        this.textures.on("addtexture", () => {
            count++;

            // note I am checking for 2
            // this is the number of textures that I
            // expect to be loaded and it MUST MATCH
            // the number of times you call addBase64
            if (count==2) {
                // move on to the next scene
                this.scene.start("game");
            }
        });

        // ask phaser3 to load the data uri
        // I am loading 2 textures this way
        this.textures.addBase64("1",mystring);
        this.textures.addBase64("2",mystring2);
    }
}

class GameScene extends Phaser.Scene {
    constructor() {
        super("game");
    }

    create() {
        // the keys "1" and "2" were loaded
        // in the LoadingTexturesOnly scene above
        this.add.sprite(100,100,"1");
        this.add.sprite(100,200,"2");
    }

}

function main() {
    let gameOpts = {
        width : 600,
        height : 800,
        scene : [LoadingTexturesOnly,GameScene]
    };
    let game = new Phaser.Game(gameOpts);
}

window.onload = main;
Enter fullscreen mode Exit fullscreen mode

References:
data url : https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs
data uri scheme: https://en.wikipedia.org/wiki/Data_URI_scheme
base64 encoding: https://developer.mozilla.org/en-US/docs/Glossary/Base64
import statement: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import
export statement: https://developer.mozilla.org/en-US/docs/web/javascript/reference/statements/export

Top comments (0)

This post blew up on DEV in 2020:

js visualized

🚀⚙️ JavaScript Visualized: the JavaScript Engine

As JavaScript devs, we usually don't have to deal with compilers ourselves. However, it's definitely good to know the basics of the JavaScript engine and see how it handles our human-friendly JS code, and turns it into something machines understand! 🥳

Happy coding!