Hi everyone,
I’m facing an issue that I can’t figure how to sort it out. The context is this: I have setup a websocket which receives an image encoded in base64 (inside a JSON). When I receive this image what I would like to do is to update the previous sprite content with the image that I’ve just received. I know that in Phaser I’m supposed to load all my assets before the whole game runs, but for this particular use case I really need to re-display a map that is computed elsewhere and is asynchronously sent to the frontend. Here is a snippet that only works the first time the map is received (this snippet is part of a larger class, but the relevant code is shown below):
onMapUpdate(message) {
let map = null;
try {
map = JSON.parse(message.data)['map'];
} catch (error) {
console.error(`Error - Couldn't parse JSON: ${message.data}. Details: ${error}.`);
}
if (map) {
this.scene.textures.addBase64('map', `data:image/png;base64,${map}`);
if (this.scene.mapSprite !== null) {
this.scene.mapSprite.setTexture('map');
} else {
this.scene.mapSprite = this.scene.add.sprite(
this.scene.settings.grid.center.x,
this.scene.settings.grid.center.y,
'map'
);
}
}
}
The onMapUpdate method is called every time the websocket receives a message. The first time this code runs it displays the map, but this only happens once as the next time the method is called this.scene.textures.addBase64 tries to create another texture under the ‘map’ key (which is duplicated from the previous call), and Phaser gives back a duplicated key error message in the console which is reasonable. Now to the above snippet what I’ve done to try to fix the duplicated texture is this:
onMapUpdate(message) {
let map = null;
try {
map = JSON.parse(message.data)['map'];
} catch (error) {
console.error(`Error - Couldn't parse JSON: ${message.data}. Details: ${error}.`);
}
if (map) {
if (this.scene.textures.exists('map')) {
this.scene.textures.remove('map');
}
this.scene.textures.addBase64('map', `data:image/png;base64,${map}`);
if (this.scene.mapSprite !== null) {
this.scene.mapSprite.setTexture('map');
} else {
this.scene.mapSprite = this.scene.add.sprite(
this.scene.settings.grid.center.x,
this.scene.settings.grid.center.y,
'map'
);
}
}
}
which basically checks for an existing ‘map’ texture and deletes it if that’s the case and then it does exactly the same logic presented in the first snippet (which creates or updates a sprite accordingly). If I do this, then I don’t get any errors in the console but the rendering is broken as Phaser shows me a small black box with a green line and a green border. I do know that the image I’m sending is fine because it is displayed correctly in the first snippet and also because I have taken the base64 payload and loaded manually into an img element in the DOM and it renders ok. I’m running on Firefox v101.0.1 and using Phaser version 3.55.2. I found little or no information on internet regarding manipulating sprites this way.
Two things I forgot to mention. In the above snippets the type of this.scene is Phaser.Scene and the this.scene.mapSprite sprite object is initialized to null.
At this point my guess is that this could be a rendering issue maybe due to the asynchronous behavior when receiving the image but I’m not sure because if that were the case then I’d expect to have the same little black box with the green border on both snippets. Has anyone faced this use case before? By this I mean receiving images from a websocket and update them on the fly in Phaser. Maybe I’m missing something silly but from the texture object documentation I couldn’t spot anything that could be of use to solve this problem.
Thanks everyone for your time,
Lucas.