Jump to content

Bug while updating text


tricksty77
 Share

Recommended Posts

Hi,

I have found a strange behavior while updating some text there is a different behavior if the text is cached(i need to cache it to change the tint) or not

In particular i have 1 button that switch between 2 images 

one images is alpha 0 and the other is alpha 1

when i press the button i change the alpha from 1 to 0 and from 0 to 1

until now all is ok.

these two sprites have 2 other child sprites and also these works like expected

those 2 other sprites have two text attached and here is where the problems lies

when i update the text property that is in these 2 texts, if the texts is set to cached, only the text that is shown is updated. the other become an empty sprite with nothing inside

823740262_2018-07-2317_33_34-Panda2.png.97ecc8c5a2807013ff6268664a163673.png

this is the starting behavior

690791448_2018-07-2317_34_13-Panda2.png.e13f607c9044e7dfc5a520989182b5e2.png

this is the expected behavior

now if i press the refresh button, the refresh button change the content of the two textboxes

and now upon pressing the button i get this empty text box (the class inside has the correct text property but the cached image is wrong)

459932868_2018-07-2317_36_00-Panda2.png.5eeb8630efc1636e0ad5d8029d21d031.png

 

game.module(
    'game.main'
)

// Required Plugins
.require(
    'plugin.essentials',
)

.body(function() {

// Required Assets
// Title Screen
game.addAsset('button1.png');
game.addAsset('button2.png');
game.addAsset('energyBut.png');
game.addAsset('click1.wav');
game.addAsset('click2.wav');
game.addAsset('Patrick.fnt');

// Main Menu Scene
game.createScene('MainMenu', {
    backgroundColor: '#ffce53',
    playerInfo: {},
    contextInfo: {},

    init: function()
    {
        // UI initialization
        this.startButton11 = new game.ForgeButton('button1.png','button2.png',0.5 * game.width, 0.2*game.height,
        'Refresh', {}, 100, 1, '#000000','#FFFFFF', function() {
                game.scene.updateEnergyText(game.scene.energyText);
                game.scene.updateEnergyText(game.scene.energyText1);

        });
        this.startButton11.addTo(this.stage)
        this.startButton11.scaleAmount=0;

        this.startButton = new game.ForgeButton('button1.png','button2.png',0.5 * game.width, 0.4*game.height,
        'Test Button', {}, 100, 1, '#000000','#FFFFFF', function() {
        });
        this.startButton.addTo(this.stage)
        this.startButton.scaleAmount=0;
        this.energyText = this.createEnergyText(this.startButton.sprite2, this.energyText, 300);
        this.energyText1 = this.createEnergyText(this.startButton.sprite, this.energyText1, 150);
        
        
    },
    
    createEnergyText: function(hook, etext, xx)
    {
        var sprite2 = new game.Sprite('energyBut.png');
        sprite2.anchorCenter();
        sprite2.position.x = xx;
        sprite2.position.y = -100;
        sprite2.addTo(hook);
        
        etext = new game.Text("x", {});
        etext.addTo(sprite2);
        etext.anchorCenter();
        etext.fontClass.letterSpacing=0;
        
        var size = 120;
        var factor = etext.height / size;
        etext.height =  size;
        etext.width = etext.width / factor;
        etext.position.y=-(size/7);
        etext.position.x=0;
        
        this.updateEnergyText(etext);
        return etext;
    },
    
    updateEnergyText: function(etext)
    {
        etext.text = 'x';
        etext.updateText();
        etext.cache = true;
        etext._cachedSprite.tint = '#000000';
        etext._cachedSprite.tintAlpha = 1;
    },
});
     
// Custom Classes
game.createClass('ForgeButton', 'Button', {
    //We extend the standard button
    staticInit: function(texture1, texture2, x, y, text, textProps, size, letterSpacing, tint1, tint2, callback) 
    {
        this.super(texture2, x, y, callback);
        this.callback = callback;
        
        this.sprite.alpha=0;
        this.sprite2 = new game.Sprite(texture1);
        this.sprite2.anchorCenter();
        this.sprite2.alpha=1;
        this.sprite2.buttonMode = true;
        
        this.sprite2.position.x = x;
        this.sprite2.position.y = y;
        this.sprite2.interactive = true;
        this.sprite2.mousedown = this.mousedown.bind(this);
        this.sprite2.mouseup = this.mouseup.bind(this);
        this.sprite2.mouseupoutside = this.mouseup.bind(this);

    
        this.text1 = new game.Text(text, textProps);
        this.text1.anchorCenter();
        this.text1.addTo(this.sprite2);
        
        this.text2 = new game.Text(text, textProps);
        this.text2.anchorCenter();
        this.text2.addTo(this.sprite);

        var factor = this.text1.height / size;
        
        this.text1.height = size;
        this.text1.width /= factor;
        this.text1.position.y=-(size/7);
        this.text1.fontClass.letterSpacing=letterSpacing;
        
        this.text1.updateText();
        this.text1.cache = true;
        this.text1._cachedSprite.tint = tint1;
        this.text1._cachedSprite.tintAlpha = 1;
        
        this.text2.height = size;
        this.text2.width /= factor;
        this.text2.position.y=-(size/7);
        this.text2.fontClass.letterSpacing=letterSpacing;
        
        this.text2.updateText();
        this.text2.cache = true;
        this.text2._cachedSprite.tint = tint2;
        this.text2._cachedSprite.tintAlpha = 1; 
        
        this.sprite2.click = this.click.bind(this);
    },
    
    addTo: function(container) {
        this.super(container);
        container.addChild(this.sprite2);
    },
    scaleIn: function(delay) {
        delay = delay || 0;
        this.sprite2.scale.set(0);
        game.Tween.add(this.sprite2.scale, {
            x: 1, y: 1
        }, this.scaleSpeed, {
            easing: this.scaleEasing,
            delay: delay,
            onStart: this._onScaleInStart.bind(this),
            onComplete: this._scaleInEnd.bind(this)
        }).start();
    },
    rotate: function(random) {
        this.super(random),
        this.sprite2.rotation = -this.rotateAmount;
        this.rotateTween = game.Tween.add(this.sprite2, {
            rotation: this.rotateAmount
        }, this.rotateSpeed, {
            repeat: Infinity,
            yoyo: true,
            easing: this.rotateEasing
        }).start();
        if (random) this.rotateTween.currentTime = this.rotateTween.duration.random();
    },
    setPosition: function(x,y)
    {
        
        this.sprite.position.x = x;
        this.sprite.position.y = y;
        this.sprite2.position.x = x;
        this.sprite2.position.y = y;
        
    },
    mousedown: function()
    {
        if (this.clickSound) game.audio.playSound(this.clickSound);
        this.sprite2.alpha=0;
        this.sprite.alpha=1;
        this.sprite.mousedown();
    },
    mouseup: function()
    {
        if (this.clickSound1) game.audio.playSound(this.clickSound1);

        this.sprite2.alpha=1;
        this.sprite.alpha=0;
        this.sprite.mouseup();
    },
    click: function()
    {
        //if (this.clickSound) game.audio.playSound(this.clickSound);
        
        if (typeof this.callback === 'function')
        {
            this.callback();
        }
    }
});


});

Many thanks

Link to comment
Share on other sites

It is a bit hard to understand and follow your code, so i'm not sure what the actual issue is.

I did find few things that did not look right:

this.energyText1 = this.createEnergyText(this.startButton.sprite, this.energyText1, 150);

You are creating new variable energyText1 but also using that as a parameter in a same line. At that point that variable would be still undefined, so you should not do that.

I would change your code to this:

    ....
    this.energyText = this.createEnergyText(this.startButton.sprite2, 300);
    this.energyText1 = this.createEnergyText(this.startButton.sprite, 150);
},

createEnergyText: function(hook, xx) {
    var sprite2 = new game.Sprite('energyBut.png');
    sprite2.anchorCenter();
    sprite2.position.x = xx;
    sprite2.position.y = -100;
    sprite2.addTo(hook);
    
    var etext = new game.Text('x');
    etext.addTo(sprite2);
    etext.anchorCenter();
    
    var size = 120;
    var factor = etext.height / size;
    etext.height = size;
    etext.width = etext.width / factor;
    etext.position.y = -(size / 7);
    etext.position.x = 0;

    this.updateEnergyText(etext);
    return etext;
},

Also i really don't understand your updateEnergyText function.

updateEnergyText: function(etext)
{
    etext.text = 'x';
    etext.updateText();
    etext.cache = true;
    etext._cachedSprite.tint = '#000000';
    etext._cachedSprite.tintAlpha = 1;
},

You are settings text value to 'x' that has already text value 'x'? What are you trying to achieve there?

If you want to change your text, you should use setText function.

 

Link to comment
Share on other sites

Ok i understand that the code is not so clean.

even with the set text the problem remain

updateEnergyText: function(etext)
{
    etext.setText('XX');

    etext.cache = true;
    etext._cachedSprite.tint = '#000000';
    etext._cachedSprite.tintAlpha = 1;
},

 

If you can try to run the code it will be clear what is the problem.

after you have pressed the refresh button the pressed text over the text button will be empty (even if there is XX inside the text property)

 

the etext parameter is not used unitialized the first line i use is etext= new blah blah

but i realized that this is not passed by ref value so i had to add the return etext (but still this had no impact on the behavior i see)

 

 

Link to comment
Share on other sites

I have cleaned the sample a little bit more and I attach all the files needed to run 

please run this sample and try the behavior

1 press and hold test button

2 press refresh

3 press and hold the test button

see the difference between 1 and 3

game.module(
    'game.main'
)

// Required Plugins
.require(
    'plugin.essentials',
)

.body(function() {

// Required Assets
// Title Screen
game.addAsset('button1.png');
game.addAsset('button2.png');
game.addAsset('energyBut.png');
game.addAsset('Arial.fnt');

// Main Menu Scene
game.createScene('MainMenu', {
    backgroundColor: '#ffce53',
    playerInfo: {},
    contextInfo: {},

    init: function()
    {
        // UI initialization
        this.startButton11 = new game.ForgeButton('button1.png','button2.png',0.5 * game.width, 0.2*game.height,
        'Refresh', {}, 100, 1, '#000000','#FFFFFF', function() {
                game.scene.updateEnergyText(game.scene.energyText);
                game.scene.updateEnergyText(game.scene.energyText1);

        });
        this.startButton11.addTo(this.stage)
        this.startButton11.scaleAmount=0;

        this.startButton = new game.ForgeButton('button1.png','button2.png',0.5 * game.width, 0.4*game.height,
        'Test Button', {}, 100, 1, '#000000','#FFFFFF', function() {
        });
        this.startButton.addTo(this.stage)
        this.startButton.scaleAmount=0;
        this.energyText = this.createEnergyText(this.startButton.sprite2, 300);
        this.energyText1 = this.createEnergyText(this.startButton.sprite, 150);
        
        
    },
    
    createEnergyText: function(hook, xx)
    {
        var sprite2 = new game.Sprite('energyBut.png');
        sprite2.anchorCenter();
        sprite2.position.x = xx;
        sprite2.position.y = -100;
        sprite2.addTo(hook);
        
        etext = new game.Text("x", {});
        etext.addTo(sprite2);
        etext.anchorCenter();
        etext.fontClass.letterSpacing=0;
        
        var size = 120;
        var factor = etext.height / size;
        etext.height =  size;
        etext.width = etext.width / factor;
        etext.position.y=-(size/7);
        etext.position.x=0;
        
        this.updateEnergyText(etext);
        return etext;
    },
    
    updateEnergyText: function(etext)
    {
        etext.setText('xx');
        etext.cache = true;
        etext._cachedSprite.tint = '#000000';
        etext._cachedSprite.tintAlpha = 1;
    },
});
     
// Custom Classes
game.createClass('ForgeButton', 'Button', {
    //We extend the standard button
    staticInit: function(texture1, texture2, x, y, text, textProps, size, letterSpacing, tint1, tint2, callback) 
    {
        this.super(texture2, x, y, callback);
        this.callback = callback;
        
        this.sprite.alpha=0;
        this.sprite2 = new game.Sprite(texture1);
        this.sprite2.anchorCenter();
        this.sprite2.alpha=1;
        this.sprite2.buttonMode = true;
        
        this.sprite2.position.x = x;
        this.sprite2.position.y = y;
        this.sprite2.interactive = true;
        this.sprite2.mousedown = this.mousedown.bind(this);
        this.sprite2.mouseup = this.mouseup.bind(this);
        this.sprite2.mouseupoutside = this.mouseup.bind(this);

    
        this.text1 = new game.Text(text, textProps);
        this.text1.anchorCenter();
        this.text1.addTo(this.sprite2);
        
        this.text2 = new game.Text(text, textProps);
        this.text2.anchorCenter();
        this.text2.addTo(this.sprite);

        var factor = this.text1.height / size;
        
        this.text1.height = size;
        this.text1.width /= factor;
        this.text1.position.y=-(size/7);
        this.text1.fontClass.letterSpacing=letterSpacing;
        
        this.text1.updateText();
        this.text1.cache = true;
        this.text1._cachedSprite.tint = tint1;
        this.text1._cachedSprite.tintAlpha = 1;
        
        this.text2.height = size;
        this.text2.width /= factor;
        this.text2.position.y=-(size/7);
        this.text2.fontClass.letterSpacing=letterSpacing;
        
        this.text2.updateText();
        this.text2.cache = true;
        this.text2._cachedSprite.tint = tint2;
        this.text2._cachedSprite.tintAlpha = 1; 
        
        this.sprite2.click = this.click.bind(this);
    },
    
    addTo: function(container) {
        this.super(container);
        container.addChild(this.sprite2);
    },
    mousedown: function()
    {
        if (this.clickSound) game.audio.playSound(this.clickSound);
        this.sprite2.alpha=0;
        this.sprite.alpha=1;
        this.sprite.mousedown();
    },
    mouseup: function()
    {
        if (this.clickSound1) game.audio.playSound(this.clickSound1);

        this.sprite2.alpha=1;
        this.sprite.alpha=0;
        this.sprite.mouseup();
    },
    click: function()
    {
        //if (this.clickSound) game.audio.playSound(this.clickSound);
        
        if (typeof this.callback === 'function')
        {
            this.callback();
        }
    }
});


});

 

button1.png

Arial.fnt

Arial_0.png

button2.png

energyBut.png

Edited by tricksty77
added resources
Link to comment
Share on other sites

updateEnergyText: function(etext)
    {
        
        etext.cache = true;
        console.log('alpha = ' + etext.alpha);
        etext.setText('xx');
        etext.alpha=1;
        etext._cachedSprite.tint = '#000000';
        etext._cachedSprite.tintAlpha = 1;
    }

 

The problem is resulting from the combination of 1: the alpha of the sprite, and 2: the setText('xx') and 3: the cache=true

I tried to dig a little into the engine, but I'm still unfamiliar with how it all ties together, so please bare with me, this is a messy response.

In text.js, setText() calls -> this._generateText() which calls container.js->updateTransform(). 

In container.js->updateTransform (at around line 511) it sets alpha: this._worldAlpha = this.parent._worldAlpha * this.alpha; If you hard-code this._worldAlpha=1 here, then your issue 'disappears', so I think this is a key point in the problem.

So I think the this.alpha (from the sprite/etext) is simply passed in as zero, gets rendered somehow, but if alpha is zero, it's rendered (And cached) as empty. I can't see in the engine where this is happening, and I've got to dash, soon.

To test: You can hard-code the parent _worldAlpha_ into your method like this:

updateEnergyText: function(etext)
    {
        etext.parent._worldAlpha = 1;
        etext.setText('xx');
        etext.cache = true;
        etext.alpha=1;
        etext._cachedSprite.tint = '#000000';
        etext._cachedSprite.tintAlpha = 1;
    }

 

That should now *work* (i.e. looks like it's doing the right thing.). But I don't really understand this caching that you're trying to be doing, and I still don't understand how Panda does all it's rendering, so.. don't consider this reply a solution by any means! 

Link to comment
Share on other sites

Thanks, this workaround  apparently resolve the issue i have.

The caching I am doing is becouse I want to change the color of the text and this seems to be the only way to go for now.

Probably this is not the most perfect way but at least it works.

Many thanks

 

Link to comment
Share on other sites

Well, this is just debugging the root cause, not really a fix. I don't quite understand caching, so I don't know if this is a bug or it's expected that you can't cache a 0 alpha sprite/text.

(If you want to go with it so you can keep making your game, as a precaution, I would do something like until we have a better idea of what is happening, because I have no idea about the rendering at the moment ( @enpu , help? :))

var temp = etext.parent._worldAlpha;
etext.parent._worldAlpha = 1;

//drawing stuff

etext.parent._worldAlpha = temp;

Just in case _worldAlpha is important for the drawing of the other sprites in the render engine, and we're messing it all up.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

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