Drawing Text using Slick 2D library

Hi,
so I finally made Slick’s UnicodeFont work! It was tricky, because i had to:
enable GL_TEXTURE_2D
draw String
disable GL_TEXTURE_2D

But now i have another problem - my font isn’t transparent. Here’s screenshot:

Notice FPS counter in upper left corner.

I’m using Orthogonal projection.

Greetings,
Sonic96PL


glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
//render
glDisable(GL_BLEND);

Written on an iPhone!

[quote=“Sonic96PL,post:1,topic:39365”]
I did this a few days ago, and you really shouldn’t need to do that. You’re probably doing something wrong, which is resulting in problems.

He really shouldn’t need to touch OpenGL directly at all when using Slick2D, if he’s using functionality within Slick (he is).

EDIT: I have gathered my code (decompiled on an Android. You’re welcome). This is how I load a font:

String fontPath = "res/font/calibri.ttf";
fpsFont = new UnicodeFont(fontPath, 15, true, false);
fpsFont.addAsciiGlyphs();
fpsFont.addGlyphs(400, 600);
fpsFont.getEffects().add(new ColorEffect(java.awt.Color.WHITE));
fpsFont.loadGlyphs();

This is how to draw it then:

fpsFont.drawString(280.0F, 300.0F, "LØL", Color.RED);

If you be wanting to write out text to the screen, you will be wanting to use the font class. (Hmm, almost works as a ‘Mario song’.)

Font, with the specific instance of Angel Code being the most accessible. You load up Hiero and create your font using it, then you just load things as is specified in the API docs. Really simple.

AngelCode is really the most accessible? I found it quite frustrating with Hiero not working. I liked the TrueType implementation, but it’s depricated now. The UnicodeFont is really not bad either. Look up. :slight_smile:

I forgot to say that i’m not using Slick library directly.
I’m using OpenGL by LWJGL API, and Slick is only for sound, textures etc. It’s “help” library.

And enabling and disabling GL_BLEND also doesn’t work :frowning: I’ve tried it before.

I also found Angel Code very annoying :frowning:

Ah, then you should probably be using the SlickUtil library, instead of the actual Slick Library (If you’re not already). Beyond that, if you’re just using your texture for the purposes of your GUI you might be better off looking into TWL or something like that.

I’m using both Slick and Slick-Util. So maybe there is a problem?
TWL also looks intresting, thank you :slight_smile:

SlickUtil is just a subset of Slick2D; i.e. the “core” classes pulled out. The SlickUtil download is a little outdated, as development has been progressing with Slick2D on bitbucket (led by the community). If you want the latest version with more bug fixes, you’d be better off pulling Slick2D in full and not using the outdated SlickUtil.

UnicodeFont is by far the worst implementation of text in Slick2D. It’s extremely slow, depends on AWT, buggy, inflexible, etc. Loading Arial can take up to 3 full seconds on my system, whereas any AngelCodeFont will be loaded in milliseconds. (Appears to be a Mac or Java2D specific bug, see below.)

UnicodeFont also seems to have a bug which is why you need to disable texturing. The proper solution (I think) is not to disable/re-enable texturing every frame, but instead do the following at the end of your game’s init():

TextureImpl.bindNone();

(This is just a guess based on past bugs – let me know if it works.)

If Hiero is giving you issue, you can use the more robust font tool from TWL and simply export the font definition as text.
http://twl.l33tlabs.org/themer/fonttool.jnlp

Really you shouldn’t UnicodeFont or TrueTypeFont except for very quick prototyping, or when you absolutely need font generation on the fly.

Regarding the problem, enable blending before you initialize the UnicodeFont to see if that resolves it.

Hey, that isn’t very nice! :stuck_out_tongue: I wrote UnicodeFont a long time ago, but it isn’t all that bad. You must be loading an enormous number of glyphs for it to take 3 seconds? It should not be any slower once the glyphs are loaded. If you don’t need Unicode support, then you are better off using bitmap fonts. UnicodeFont is for supporting loading glyphs on the fly, for CJK and other fonts with too many glyphs and/or combining marks. Right tool for the job and all that. :slight_smile: AFAIK, there isn’t an alternative for UnicodeFont for Slick or any other lib. Some libs (JOGL?) can draw strings of characters, which comes close but isn’t a replacement if your app allows arbitrary text entry.

Sorry, my last post was a little harsh. UnicodeFont is good at what it does (unicode support, effects, and on-the-fly generation), so let me rephrase:

[quote]UnicodeFont is the worst choice if you want simple fixed-size ASCII text
[/quote]
Regarding load times – a very rough benchmark on my machine:
AngelCodeFont: ~30 ms (512x512 image, Arial 72 pt)
TrueTypeFont: ~2500 ms (Verdana, 16 pt)
UnicodeFont: ~3700 ms (Verdana, 16 pt)

This is, of course, loading all ascii glyphs upfront. Ideally you would load a couple glyphs per frame with UnicodeFont, but the result of glyphs “popping” into frame doesn’t look too pleasing.

Regarding load times – a very rough benchmark on my machine:
AngelCodeFont: ~30 ms (512x512 image, Arial 72 pt)
TrueTypeFont: ~2500 ms (Verdana, 16 pt)
UnicodeFont: ~3700 ms (Verdana, 16 pt)

This is, of course, loading all ascii glyphs upfront. Ideally you would load a couple glyphs per frame with UnicodeFont, but the result of glyphs “popping” into frame doesn’t look too pleasing.
[/quote]
This is very misleading. Can you please post your benchmark code for UnicodeFont? You must be doing something that I’m not.


while (true) {
	long s = System.nanoTime();
	UnicodeFont unicodeFont = new UnicodeFont(new Font("Verdana", Font.PLAIN, 16));
	unicodeFont.getEffects().add(new ColorEffect());
	unicodeFont.addAsciiGlyphs();
	unicodeFont.loadGlyphs();
	long e = System.nanoTime();
	System.out.println((e - s) / 1e6f + "ms");
}

Admittedly this is using the UnicodeFont from the Hiero in libgdx, but it should be the same as the one in Slick (or someone broke the one in Slick).

		java.awt.Font f = new java.awt.Font("Verdana", java.awt.Font.PLAIN, 16);
		long i = System.currentTimeMillis();
		ufont = new UnicodeFont(f);
		ufont.getEffects().add(new ColorEffect(java.awt.Color.white));
		ufont.addAsciiGlyphs();
		ufont.loadGlyphs();
		System.out.println("Time taken: "+(System.currentTimeMillis()-i)+" ms");

Full (Slick) source using dev branch code:
http://www.java-gaming.org/?action=pastebin&id=179

If it’s a bug, I’d love to fix it. Typical time is around ~3700 ms.

For the record:
Mac OS 10.6.6
4GB RAM
3.06 GHz Intel Core 2 Dueo
NVidia GeForce 9400

Thank you all for your support!

  1. Slick-Util doesn’t have Unicode and even AngelCode class. It only have TrueTypeFont class :frowning:

TextureImpl.bindNone();

doesn’t work at all.

  1. For me loading time is not important. Better question is how much memory it takes?
    (for me it takes 4sec to load :wink: that’s fine)

  2. Can somebody explain me how to set up AngelCodeFont properly? I can’t fint it anywhere. I don’t know how .png file must look like.

I’m doing it all the time. Still font with black background.

Again thank you all for such a great discussion, and help.
Also sorry for my english :slight_smile:

Greetings,
Sonic96PL

Thanks, interesting. I’ll look into the bug.

[quote]3. For me loading time is not important. Better question is how much memory it takes?
(for me it takes 4sec to load :wink: that’s fine)
[/quote]
Yikes – 4 seconds is crazy… And probably slows down your productivity more than you realize, if you’re waiting that long every time you run your game. Don’t expect your users to be happy, making them wait 4 seconds instead of 20 milliseconds. :slight_smile:

Once UnicodeFont is created, it acts pretty much identically to AngelCodeFont in terms of performance/memory. In other words, you can look at UnicodeFont as a means of generating “AngelCodeFonts” on the fly.

UnicodeFont may be slightly less efficient regarding getWidth/getHeight/etc which relies on layoutGlyphVector, but the difference will probably not be huge.

[quote]4. Can somebody explain me how to set up AngelCodeFont properly? I can’t fint it anywhere. I don’t know how .png file must look like.
[/quote]

  1. Open the TWL Font Tool I linked earlier.
  2. Open a font you would like. Set the size and so forth.
  3. In the lower right of the font tool, you’ll see a drop-down that says “XML” – change it to “Text”.
  4. Save the file somewhere. You’ll end up with two files: a PNG and FNT. Move those to your resources folder.
  5. Use the following code in Slick:
Font font;

font = new AngelCodeFont("res/myfont.fnt", "res/myfont.png");

[quote]5. I’m doing it all the time. Still font with black background.
[/quote]
No idea then. Let us know if AngelCodeFont changes anything – if you’re getting issues with that, too, then it probably means you haven’t enabled blending correctly.

I’ve not used slick2d lately but I think I can remember how to do this :smiley:

-First of all download and install Bmfont: http://www.angelcode.com/products/bmfont/
-Open it, press options>font settings and select the font and the size, press ok.
-At the main screen you can see checkboxes, press the first one.
-Now options>export options in textures select png, press ok.
-If you press options>visualize you can see how the image will look.
-Finally press options>save bitmap font as… It will give you a png file and a fnt one.

Now in Java:

-Load the png Image:

public static Image theImage= new Image("/data/images/font.png",false,Image.FILTER_NEAREST);

-Load the AngelCodeFont:

public static AngelCodeFont font= new AngelCodeFont("/data/images/font.fnt",theImage);

And then just render it:

font.drawString(x, y, "It's easy!"); 

Hope it helps :slight_smile:

EDIT: someone posted before me :c Well if you are using slick2D keep it simple, don’t use the lwjgl methods because you don’t need to :slight_smile:

AngelCodeFont:

That’s something about Textutes, I think.
So all of my init code:

glShadeModel(GL_SMOOTH);
		
glEnable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);

and some of my switching mode method code:

	public static void setupGL(int mode) {
		
		if(mode == M_3D) {
			
			glMatrixMode(GL_PROJECTION);
			glLoadIdentity();
			
			gluPerspective(45f, Main.WIDTH / Main.HEIGHT, nearZ, farZ);
			glMatrixMode(GL_MODELVIEW);
			
			currentMode = M_3D;
		}
		
		if(mode == M_2D) {			
			glMatrixMode(GL_PROJECTION);			
			glPushMatrix();
			glLoadIdentity();
			
			gluOrtho2D(0, Main.WIDTH, 0, Main.HEIGHT);
			
			glScalef(1, -1, 1);
			glTranslatef(0, -Main.HEIGHT, 0);
			glMatrixMode(GL_MODELVIEW);
			
			currentMode = M_2D;
		}
		
		if(mode != M_2D && mode != M_3D) {
			System.err.println("No such mode: " + mode);
		}
	}

I’ll keep trying to setup TWL.

Thank you for your help.
Sonic96PL

EDIT: I’m drawing text while in M_2D mode.

EDIT2:

TWL is awesome. Thx for your help! ;D

I got Slick from SVN and tried your test.
Time taken: 129 ms
That’s on Windows 7. I’m afraid you’ll have to debug the issue on your setup, if you’d like to see it improved.

Haha, guys I know what was wrong!

Before:

glEnable(GL_TEXTURE_2D);

font.drawString(10, 10, FpsCounter.getFps() + " fps");

glDisable(GL_TEXTURE_2D);

After:

glEnable(GL_TEXTURE_2D);
glDisable(GL_DEPTH_TEST);

font.drawString(10, 10, "FPS: " + FpsCounter.getFps());

glEnable(GL_DEPTH_TEST);
glDisable(GL_TEXTURE_2D);

So the key thing was GL_DEPTH_TEST :stuck_out_tongue:
Also UnicodeFont was loaded in 202 ms. Good work!

Greetings,
Sonic96PL

Just a heads up – turns out the loading issue was because of ASCII glyphs above 127. By default, addAsciiGlyphs uses code points 32-255. By specifying addGlyphs(32, 127) my load speeds go down to ~80 ms, which is definitely manageable. :slight_smile:

Seems like a Mac or Java2D issue. I’ll test it out on my other computer.