Jump to content

Center BitmapText


Recommended Posts

Hello, in previous versions it was possible to center a BitmapText object by using anchor.setTo(0.5, 0.5). Is there an equivalent way of doing this in 1.2? I know that there is the align property but what I'm trying to do is to make the text appear in the center of the screen regardless of its width or height; which is what the anchor aided in doing.

Link to post
Share on other sites
  • 2 weeks later...

I tried that, but the problem is there doesn't seem to be an anchor property on BitmapText anymore.

Edit: It seems that the alternative is to use the textWidth property to manually center the text.

 

Could you please more information on how you solved this? Having exactly the same problem but not sure how to apply that.

Thanks :)

Link to post
Share on other sites

Hey, sure I did it like this:

this.scoreText = this.game.add.bitmapText(0, 15, 'mecha', '0', 40);this.scoreText.align = 'center';this.scoreText.x = this.game.width / 2 - this.scoreText.textWidth / 2;//then whenever you set the text, you need to reposition it:this.scoreText.setText('100');this.scoreText.x = this.game.width / 2 - this.scoreText.textWidth / 2;
Link to post
Share on other sites

OK, tested this and see no solution, other than waiting for text to be updated, and position it making the necessary calculations according to its width and height, which is a very bad solution since width and height can't be calculated at the time the text is updated.

 

Reading Rich's post #2, I think something's wrong, and anchor property should still be available.

Link to post
Share on other sites

 

I think you can calculate width and height with updateTransform method, like:

text.setText('test');text.updateTransform();text.position.x = 100 - text.textWidth / 2;

 

Thank you very much! That worked just fine :)

Still missing the good old anchor point, but that will do the job until it comes back (in case it does).

Link to post
Share on other sites
  • 2 weeks later...
  • 2 weeks later...
  • 1 month later...

The updateTransform method updates the bounds of the object (which you then get via getBounds or getLocalBounds) but you can also get the width of a BitmapText instance by calling its updateText method - this is called automatically when you first create a new instance, but should be manually called if you alter the text.Then you can get its width from its textWidth property correctly, as this is updated during updateText, and not necessarily during updateBounds. Something like:

bitmapText.updateText();bitmapText.x = game.world.centerX - (bitmapText.textWidth * 0.5);

Will center the bitmapText in your world by placing it at the center, then offsetting it by half its width (multiplying by 0.5 is the same as dividing by 2, but is faster - a good habit to get into when writing performant code).

Link to post
Share on other sites

Interesting, I wonder why they're private? There are definitely use cases for needing to force an updateTransform or updateText synchronously so that you can access the dimensions of an object instantly rather than waiting for the dirty flag to be checked on the next update. Does anyone know if there's another way we should be doing this kind of stuff?

Link to post
Share on other sites
  • 1 month later...

Here is the solution:

 

Object.defineProperty(Phaser.BitmapText.prototype, 'anchor', {    get: function() {        return this._anchor;    },    set: function(anchor) {        this._anchor = anchor;        this.dirty = true;        this.updateTransform();                if (!this.textBitmapSpritesParent)        {            this.textBitmapSpritesParent = new Phaser.Group(this.game);            this.addChild(this.textBitmapSpritesParent);        }        this.textBitmapSpritesParent.x = -this.textWidth * this.anchor.x;        this.textBitmapSpritesParent.y = -this.textHeight * this.anchor.y;                for (var i = 0; i < this.children.length;)        {            if (this.children[i] == this.textBitmapSpritesParent)            {                ++i;            }            else            {                this.textBitmapSpritesParent.add(this.children[i]);            }        }     }});

 

PS: rich, this would work better (more reliable) if BitmapText would use an internal dedicated array for its Glyph sprites.

Link to post
Share on other sites

Better solution:

 


Paste this somewhere in your 'extensions.js' (after loading phaser-min.js) and it'll work.

 

Object.defineProperty(Phaser.BitmapText.prototype, 'anchor', {    get: function() {        return this._anchor;    },    set: function(anchor) {        this._anchor = anchor;        this.dirty = true;        this.updateTransform();    }});PIXI.BitmapText.prototype.updateText = function(){    var data = PIXI.BitmapText.fonts[this.fontName];    if (!data)    {        console.error("Bitmap font not found: '" + this.fontName + "'");        return;    }         var pos = new PIXI.Point();    var prevCharCode = null;    var chars = [];    var maxLineWidth = 0;    var lineWidths = [];    var line = 0;    var scale = this.fontSize / data.size;        for(var i = 0; i < this.text.length; i++)    {        var charCode = this.text.charCodeAt(i);        if(/(?:\r\n|\r|\n)/.test(this.text.charAt(i)))        {            lineWidths.push(pos.x);            maxLineWidth = Math.max(maxLineWidth, pos.x);            line++;            pos.x = 0;            pos.y += data.lineHeight;            prevCharCode = null;            continue;        }        var charData = data.chars[charCode];        if(!charData) continue;        if(prevCharCode && charData[prevCharCode])        {            pos.x += charData.kerning[prevCharCode];        }        chars.push({texture:charData.texture, line: line, charCode: charCode, position: new PIXI.Point(pos.x + charData.xOffset, pos.y + charData.yOffset)});        pos.x += charData.xAdvance;        prevCharCode = charCode;    }    lineWidths.push(pos.x);    maxLineWidth = Math.max(maxLineWidth, pos.x);    var lineAlignOffsets = [];    for(i = 0; i <= line; i++)    {        var alignOffset = 0;        if(this.style.align === 'right')        {            alignOffset = maxLineWidth - lineWidths[i];        }        else if(this.style.align === 'center')        {            alignOffset = (maxLineWidth - lineWidths[i]) / 2;        }        lineAlignOffsets.push(alignOffset);    }    var lenChildren = this._pool.length;    var lenChars = chars.length;    var tint = this.tint || 0xFFFFFF;    for(i = 0; i < lenChars; i++)    {        var c = this._pool[i];        if (c) c.setTexture(chars[i].texture); // check if got one before.        else        {            c = new PIXI.Sprite(chars[i].texture); // if no create new one.            this._pool.push(c);        }        c.position.x = (chars[i].position.x + lineAlignOffsets[chars[i].line]) * scale;        c.position.y = chars[i].position.y * scale;        c.scale.x = c.scale.y = scale;        c.tint = tint;        if (!c.parent) this.addChild(c);    }    // remove unnecessary children.    // and put their into the pool.    for (var i = lenChars; i < this._pool.length; ++i)    {        this.removeChild(this._pool[i]);    }    /**     * [read-only] The width of the overall text, different from fontSize,     * which is defined in the style object     *     * @property textWidth     * @type Number     */    this.textWidth = maxLineWidth * scale;    /**     * [read-only] The height of the overall text, different from fontSize,     * which is defined in the style object     *     * @property textHeight     * @type Number     */    this.textHeight = (pos.y + data.lineHeight) * scale;    if (this._anchor)    {        for(i = 0; i < lenChars; i++)        {            var c = this._pool[i];            c.position.x -= this.textWidth * this._anchor.x;            c.position.y -= this.textHeight * this._anchor.y;        }    }};
Link to post
Share on other sites
In all seriousness, regardless of what internal structure an object has, I want to set its anchor point. Imagine a list of numbers, for instance a high score list. I want the back of the numbers to align.

 

Now if these labels are TTF text or bitmap font texts are not important to me. I want to be able to align them the same way.

 

In my vision, "align" doesn't address this issue because that specifies how the text should be aligned _within_ the label and therefore only has effect on labels with *multiple lines*.

 

As one game engine developer (c++) to another (JS), I highly recommend adding the "anchor" property on every type of visual world object with a width & height.

 

PS: how can I change the 'Newbie' status above my profile picture without having to make too much posts? :-)

Link to post
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...
  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...