Jump to content
This forum will be closing down. Please move to the respective dedicated project forums.

Updating existing texture with canvas content


unlink2
 Share

Recommended Posts

Hello,

As many of you I have recently started using Phaser 3. I've been trying to use a normal 2D canvas as a texture and update a texture in the TextureManager without recreating the canvas.
Is this possible?
My current approach works, but is leaking memory all over the place which I do not want of course.
Here's what I have tried so far.

this.canvasTexture = this.game.textures.createCanvas(this.id + '_aelu', 320, 200);
this.createScreen();
createScreen() {
        this.canvas = this.canvasTexture.getSourceImage();
        this.context = this.canvas.getContext('2d');
        this.imageData = this.context.getImageData(0, 0, 320, 200);
        this.pixelArray = this.imageData.data;

        this.context.clearRect(0, 0, 320, 200);
        for (var p = 0; p < this.pixelArray.length / 4; p++) {
            var index = 4 * p;

            this.pixelArray[index] = Math.random() * Math.floor(255); // r
            this.pixelArray[++index] = Math.random() * Math.floor(255); // g
            this.pixelArray[++index] = Math.random() * Math.floor(255); // b
            this.pixelArray[++index] = 255; // a
        }

        // this does not update the actual texture
        this.context.putImageData(this.imageData, 0, 0);

        // this would be nice, but it seems like it does not actually update the texture?
        // this.canvasTexture.setDataSource(this.canvas);

        // this updates the texture but causes huge memory issues
        /* this.game.textures.get(this.id + '_aelu_out').destroy();

        this.game.textures.addSpriteSheet(this.id + '_aelu_out', this.canvasTexture.getSourceImage(),          {
            frameWidth: 320,
            frameHeight: 200,
        });*/
 }

Thanks for any pointers in the right direction :>

Link to comment
Share on other sites

This changed in 3.7 so it now returns a CanvasTexture object, which is a lot easier to work with. Try the following:

var config = {
    type: Phaser.AUTO,
    parent: 'phaser-example',
    scene: {
        create: create
    }
};

var texture;

var game = new Phaser.Game(config);

function create ()
{
    texture = this.textures.createCanvas('gradient', 16, 256);

    //  We can access the underlying Canvas context like this:
    var grd = texture.context.createLinearGradient(0, 0, 0, 256);

    grd.addColorStop(0, '#8ED6FF');
    grd.addColorStop(1, '#004CB3');

    texture.context.fillStyle = grd;
    texture.context.fillRect(0, 0, 16, 256);

    //  Call this if running under WebGL, or you'll see nothing change
    texture.refresh();

    //  Add a bunch of images that all use the same texture
    for (var i = 0; i < 64; i++)
    {
        var image = this.add.image(8 + i * 16, 0, 'gradient');

        this.tweens.add({
            targets: image,
            y: 650,
            duration: 2000,
            ease: 'Quad.easeInOut',
            delay: i * 62.5,
            yoyo: true,
            repeat: -1
        });
    }

    this.time.addEvent({ delay: 4000, callback: updateTexture, callbackScope: this, loop: true });
}

function updateTexture ()
{
    var grd = texture.context.createLinearGradient(0, 0, 0, 256);

    grd.addColorStop(0, generateHexColor());
    grd.addColorStop(1, generateHexColor());

    texture.context.fillStyle = grd;
    texture.context.fillRect(0, 0, 16, 256);

    //  Call this if running under WebGL, or you'll see nothing change
    texture.refresh();
}

function generateHexColor ()
{
    return '#' + ((0.5 + 0.5 * Math.random()) * 0xFFFFFF << 0).toString(16);
}

 

Link to comment
Share on other sites

 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...