Jump to content

BitmapFont Atlas


mariogarranz
 Share

Recommended Posts

I have around 4 or 5 different bitmap fonts being used in my game. I want to move them all into a single texture Atlas, using Texture Packager.

The standard procedure for this kind of use is loading the whole .png atlas and then defining each font into the code by:

 

1 - The subtexture in the atlas for each font.

2 - The XML definition file for each font.

 

In Phaser, however, the Loader class will take a whole URL for the texture file, and I don't think it's possible to reference just a subtexture of the atlas.

 

Is there any way to use a texture atlas for multiple BitmapFonts? Or do I really need 5 separate .png files for this?

Thanks.

Link to comment
Share on other sites

You can give it an XML data object rather than URL, then it will use that instead.

 

Please note though that the XML definitions contain specific pixel offset values per character - and it's up to you to adjust all of those first to compensate for the image being part of an atlas, as Phaser won't do it automatically.

Link to comment
Share on other sites

  • 4 weeks later...

You can give it an XML data object rather than URL, then it will use that instead.

 

 

I'm not sure what this means as far as code... do you mean:

this.game.load.bitmapFont('CascadeVal122', 'atlas.xml', 'CascadeVal122.fnt');

Where 'atlas.xml' is the TextureAtlas xml that contains the font image bitmap?

 

What I would like to be able to do is just load the font xml (the .fnt) essentially passing null for the textureURL. And then when the preloader stage is finished I would wire up the font definition to the loaded texture image.

Link to comment
Share on other sites

  • 11 months later...

When creating a BitmapFont object, yes it will use the cache always. But if you're calling game.load.bitmapFont over and over then it would put each one into the cache (if you gave them unique cache keys).

There is no BitmapFont object/class, only BitmapText object/class.

game.load.bitmapFont is the only way to create an bitmapFont.

 

See the addBitmapFont method of Cache object:

game.cache.addBitmapFont (key, url, data, xmlData, xSpacing, ySpacing) 

 

We can write another method similar to addBitmapFont but without url. for example:

game.cache.addBitmapFontByAtlas (key, xmlData, imageKey, frameKey, xSpacing, ySpacing)

 

just extend the Phaser.Cache.prototype.

Phaser.Cache.prototype.addBitmapFontByAtlas = function (key, xmlData, imageKey, frameKey, xSpacing, ySpacing){   //implement code};

then we can use like this

function create(game) {    game.cache.addBitmapFontByAtlas('font2', xmlDocument, 'atlas', 'font2', 0, 0);    game.add.bitmapText(80, 260, 'font2', 'Hello');}
Link to comment
Share on other sites

  • 1 year later...

It's been over 2 years, but I finally worked this out :) 

I suspected we would get a significant reduction in draw calls by putting the bitmap font on the main game sprite sheet, and it worked. In our case about 40% drop in number of draw calls! Over many Phaser updates I still didn't see a built-in way to do it, so here is the code:   

    // EXTEND cache to allow bitmap fonts on another atlas
    Phaser.Cache.prototype.addBitmapFontByAtlas = function (key, sheetKey, sheetFrame, atlasData, atlasType, xSpacing, ySpacing) {

      var obj = {
          font: null,
          base: this.game.cache.getBaseTexture(sheetKey)
      };

      if (xSpacing === undefined) { xSpacing = 0; }
      if (ySpacing === undefined) { ySpacing = 0; }

      // bind the atlas data to the frame on the 'sheet'
      var frameData = this.game.cache.getFrameByName(sheetKey, sheetFrame);

      // only works with XML for now
      var xml = atlasData;
      var info = xml.getElementsByTagName('info')[0];
      var common = xml.getElementsByTagName('common')[0];

      var letters = xml.getElementsByTagName('char');

      for (var i = 0; i < letters.length; i++)
      {
          var x = parseInt(letters[i].getAttribute('x'), 10);
          var y = parseInt(letters[i].getAttribute('y'), 10);

          letters[i].setAttribute('x', x+frameData.x);
          letters[i].setAttribute('y', y+frameData.y);
      }


      if (atlasType === 'json')
      {
          obj.font = Phaser.LoaderParser.jsonBitmapFont(atlasData, obj.base, xSpacing, ySpacing);
      }
      else
      {
          obj.font = Phaser.LoaderParser.xmlBitmapFont(atlasData, obj.base, xSpacing, ySpacing);
      }

      this._cache.bitmapFont[key] = obj;

    };    

In order to use this, just load your 'fnt' (xml data) separately and then bind it to your main sheet:


preload: function() {
   // Load the xml data associated with your font...
   this.game.load.xml('roboFNT', fontFolder+'/roboFont.fnt');
},

create: function() {
   
   // Bind the font atlas data to the spritesheet that has the font image data...
   // In this example 'ui' is my main spritesheet, and 'robo.png' is the frame on that sheet with the font glyph image set. 
   // 'robo' is the key that you use as your font name when creating bitmap text.
   this.game.cache.addBitmapFontByAtlas('robo', 'ui', 'robo.png', this.game.cache.getXML('roboFNT'));
}

Link to comment
Share on other sites

Hi,

 some time ago I wrote blog post (http://sbcgamesdev.blogspot.cz/2016/03/phaser-tutorial-merging-fonts-into.html) about my solution: 1] how to add fonts generated in Littera into atlas, 2] how to load it into Phaser,

 Beside this, I found very useful way hot to mix small images into font, so I can print it inside string like a text - http://sbcgamesdev.blogspot.cz/2016/07/phaser-tutorial-fun-with-bitmap-fonts.html. This is single line of bitmap text:

bitmapFont.png

Link to comment
Share on other sites

 Share

  • Recently Browsing   0 members

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