Tutorial: Bitmap Fonts & Hiero
Search my cocos2d for iPhone FAQs & Tutorials
Please note that the blog search in the upper right corner doesn’t search my FAQs and Tutorials.- Note: please do not share direct download links to PDF files, the download links expire after a couple minutes!
You may have read this statement in the cocos2d API reference: CCLabel objects are slow. Consider using CCLabelAtlas or CCBitmapFontAtlas instead.
Why CCLabels are actually fast!
If you create a CCLabel object once and then just display it without ever changing its text, it's going to be just as fast as any CCSprite of the same size!
Only changing the text of a CCLabel is slow!
If you use the
[label setString:@"Hello World!"];
method to change the string or text displayed by the CCLabel, that's where a CCLabel object is slow. It's also slow of course when you first create it, so creating and throwing away a CCLabel object is as slow as changing an existing label's text.
Whenever the text of a CCLabel is changed, it's existing texture with the existing text is thrown away. Then a new texture is generated and the new text is rendered onto the texture using the iPhone SDK's font rendering mechanisms. Altogether this is a process which isn't meant to be used by realtime applications.
In the Speedtest demo you'll notice the moving sprites will jump every second. The fps display is updated too slowly to catch these minute hickups but the human eye will see it!
When a CCLabel is really, really slow ...
You may get away with CCLabels and changing their texts if that doesn't happen too often. But even changing a CCLabel once a second can cause regular framerate stuttering. Players will notice this by seeing otherwise smoothly moving objects suddenly jump for a small distance.
Once you get down to updating a CCLabel's text once per frame, even a single CCLabel of size 30 and just one letter can seriously kill your performance. On my iPhone 3GS the framerate drops to 30 fps or below when I update such a label's text every frame. Not good.
Note: I badly faked the FPS display on the screenshot because the screenshot was taken in Simulator where my Mac is powerful enough to run it at 60 fps (darn, stupid computer, can't do a damn thing right). On my iPhone 3GS however I get about 25 fps. I swear! :)
CCLabel Speed Test Xcode Project
Download the CCLabel Speedtest project.
Make sure to run it on the device. Measuring or even estimating performance in Simulator is futile. The device is where performance is accurate and measurable, and also where it counts.
I've included a 5 updates per frame mode too, in case the performance drop won't be easily noticeable on 3GS, iPad or iPhone 4 devices.









Thanks for putting this together. At first I thought I was going crazy - I’ve been using Hiero for a few months now, and early on it worked fine. I’m not sure what happened, but now I am getting the upside-down images when before I wasn’t (what a pain). I’m also having a lot of trouble with the artifacts around the sides of letters - when I add 1 pixel padding, it worked but still had artifacts. When I add 2 pixel padding, for some reason all of the offsets are incorrect (instead of ‘S’ I get half of ‘R’), arggg…. This is something I can probably fix if I go through the file and look at the actual values for manual correction, but it makes it very difficult for quick tests. Please let us know if you learn any more about how to work around these issues
The mirror image issue is really strange. It too worked for me for the first few fonts, but then it started creating only mirror images. I have the feeling once the bug appears it’s going to stay. Maybe it might help to delete Hiero so that any saved settings are deleted, then redownload it to another location.
With the padding I recommend to pad equally, if you pad 1 pixel to the right you should also pad 1 pixel to the left. It’s more a hunch though, I got the feeling that padding both sides equally might be better than padding one side with 0 and the other with 2.
Your problem may require changing the X/Y offsets too. I’m not sure what they do and I didn’t see any noticeable effect.
[...] Tutorial: Bitmap Fonts with Hiero (tags: cocos2d iphone cocoatouch) [...]
Hello, Steffen.
Good tutorial, man. I got two questions about CCBitmapFontAtlas:
1. Is there another program or way to make bitmap font atlases? Hiero has some serious bugs.
2. Using cocos2d, I need to show damage points (numbers) over every enemy I hit. Should I create CCBitmapFontAtlas variables every time I hit an enemy or there is another way to achieve this?
Thanks for your time.
There’s a programm called BMFont that is also quite popular. I think it’s for Windows though.
You can update the string of a label (bitmap font or regular) by using the setString method: [label setString:@"new text"];
To solve the mirror image issue, open the .png file ->Tools->flip vertical
Now save this file and add it to the resource folder.
ALL THE BEST
If you are getting garbage characters - look at the Hiero output PNG in Preview. If the characters are upside down, then go to “Tools” -> “Flip Vertical”. Then “Save”. And now you’ll (finally!) see characters when using the font with CCLabelBMFont.
Hopefully this saves others some time.
Please help me! I did everything as you did, but when I change the initialization line as well as the declaration in the header file, I get the following error:
Undefined symbols:
“_OBJC_CLASS_$_CCBitmapFontAtlas”, referenced from:
objc-class-ref-to-CCBitmapFontAtlas in HelloWorldScene.o
ld: symbol(s) not found
collect2: ld returned 1 exit status
But thank you for the tutorial, and your book is awesome!
Which version of Cocos2D are you using?
I’m using the latest version, 0.99.5.
CCBitmapFontAtlas and bitmapFontAtlasWithString is deprecated. You should now use CCLabelBMFont and labelWithString instead like this:
CCLabelBMFont* bfa = [CCLabelBMFont labelWithString:@"10\nAnother row" fntFile:@"pixelfont.fnt"];
Good book Steffen:)
Thank you!
Hi,
I was wondering if I can add ttf fonts to Hiero?
Thanks.
You can, there’s a “open file” dialog somewhere in the upper left corner of the Hiero dialog where you can open and select any TTF font to use.
Heiro won’t save the font file. It manages to save the settings file properly but when I try to save the font, nothing happens. Any thoughts?
Hiero is buggy, it often helps to just restart it. Otherwise consider using the commercial Glyph Designer, an excellent replacement for Hiero.
Hey Steffen. Thanks for the tutorial. I am trying to make a BIG font. I made a 2048 X 2048 bitmap. the ipad took it but took a big memory hit. So now I am playing around with trying to use multiple pngs. Is this even possible? Ive managed to get characters about 170 pxls tall on one page. But I need 3x that. what would you recommend?
I recommend to reconsider your font needs. 2048×2048 means your font will use up 16 MB of memory (assuming it’s a 32 bit PNG uncompressed). If you split this up into multiple PNGs but end up using the same total texture space you don’t win anything. Eg if the entire font only fits into 2048×2048 pixels you’re better off just using that single texture.
You should also check if you really need all characters. In Hiero you can change which characters will actually be created, if you only need uppercase letters plus digits you can limit the text to those letters, saving some space. Other than that, if your text ingame does not change while playing you can also use regular TTF fonts and CCLabelTTF in cocos2d. Same performance as sprites if you don’t change the label text.
Hi Steffen. Thanks for grate tutorial. Do you have any ideas how to create bitmap font not from TTF font, but from one bitmap image. I’ve got such image with all characters I need, but how to create a “fnt” file for it?
That’s not supported by Hiero or Glyph Designer, at least not at the moment.
However you should be able to use the font using CCLabelAtlas: http://cocos2d-iphone.org/api-ref/1.0.0/interface_c_c_label_atlas.html
Thanks for this idea. I’ll try to use CCLabelAtlas. But I want to understand how this “fnt” file in BMfonts works. Do you know where I can get specification for this file?
The .fnt format is a text-based format, so you can review it in any text editor. You might also want to review the fnt loading code in cocos2d to understand how the format works. From what I remember it’s a fairly simple format.
You’re right. Thanks. By the way. I found out that BM Font Generator from AngelCode is able to do exactly what I needed - composing bitmap font (*.fnt and corresponding *.png file) from set of separate chars images. So if you have a set of png images (one for every char in your font) you can easily compose a bitmap font. I think that it’ll be useful if you include this information as a remark to your tutorial.
I can’t install the Hiero under the environments of the Win7 64 bit. Of course I ‘ve already the Java kit 6-Java SE develoment kit 6 update 23(64-bit).
I tried to install in another PC, which is Win7 32 bit. It’s okay and works fine, even though happens to fall in the deadlock when I quit the hiero program.
Has there been any trouble with the color interpreted by cocos2d? I am using ‘CCLabelBMFont’ instead of ‘CCBitmapFontAtlas’ because the latter is marked as deprecated. When I add the font to my program, it displays as a different color (darker).
cheers
-
great book by the way.
Please ignore this comment - I was too hasty to try and blame someone else’s code before looking at my own (and too hasty to ask for help).
but it is still a great book.
Not that I know of. Do you maybe inadvertently change the color or opacity properties of the label?
That indeed was the case - sorry for wasting your time!!! :/
Does anybody know how to enable russian fonts? CCLabelBMFont *musicOnLabelText = [CCLabelBMFont labelWithString:@"Music ON" fntFile:@"cyro4asci.fnt"] works fine. But when I change it to CCLabelBMFont *musicOnLabelText = [CCLabelBMFont labelWithString:@"Музыка Вкл" fntFile:@"cyro4asci.fnt"] it shows nothing. cyro4asci.png file includes russian letters.
In CCLabelBMFont change this line:
// how many characters are supported
kCCBMFontMaxChars = 2048, //256,
to include all possible unicode characters:
// how many characters are supported
kCCBMFontMaxChars = 0xffff,
Note that this will consume 2 MB of memory per CCLabelBMFont.
Thank you very much for your reply. Unfortunately, changing kCCBMFontMaxChars = 2048, //256 to kCCBMFontMaxChars = 0xffff didn’t solve the problem. May be any other suggestions about it?