Monkey Fighter Monkey Fighter
Games Help Help Search Search Shop Shop
Asteroids

Lesson 4: Fonts

3D Game Programming - Java Programming Language

OpenGL Game Programming For the Web!

Home Page

3D Asteroids Home

Files

Lesson4.zip

Lessons

1. Models
2. Actors
3. Keyboard
4. Fonts
5. Collisions
6. Timing
7. Particles

Play Now!

3D Asteroids Normal
3D Asteroids Tiny
3D Asteroids 800x600
3D Asteroids 1024x768

Find Books

- Java Game Coding
- Game Programming
- Java Programming
- OpenGL



Java Game Programming
Developing Games in Java


Java Game Programming
Java Game Programming

To solve the problem of cross platform font support in an OpenGL environment, I developed a custom font processor in the game engine. A file containing the font model data is the only requirement for using fonts. As such, I supplied a very simple font that uses very few polygons called "Basic". You can use the this font or you can make your own. If you understand how to make models using the glo file format then you'll have no problem making fonts. That is because the font files format (glf) is exactly the same as the glo file format except that it accepts an extra keyword, START xxx, where xxx is a three digit ASCII value. The font file format is simply a list of models in glo format separated by the START xxx keyword.


Warnings about using the Basic font

Basic.glf contains all capital letters, all ten numbers, the period and the colon. It does not contain any other ASCII character. So, if you try to use a character that is not contained in the file (small letters for example), your program will crash. You can avoid crashes by not using those characters, by adding those characters to the file or by waiting until I release a game with those characters appended to the file. But, don't expect future game engines to more robust. I don't believe in writing error handling code for personal projects.


The Code

  Actor[] aScore = new Actor[6];
  GLFont fntBasic;
  int score
								

Three new global variables are introduced here. The first, aScore[] is an array of 6 actors which is used to display the score. fntBasic is a reference to the font that will display the score (among other things). And finally, score manages the current score.


  private void addScore(int a)
  { int s, v;

    s = score += a;
    for(int t=0; t<6; t++)
    { v = s%10;
      s /= 10;
      gEngine.setGLLetter(fntBasic, aScore[t], v+48);
  }

This method accepts the integer parameter, a, and adds it to score. The actors that display the score are then updated to reflex this change of score. It does this by iterating through the six score digits. By successively dividing the score by 10 each iteration, successive powers of ten (the next digit) are derived with the modulo operator. Then, the digit's actor is is updated with the setGLLetter method.


    gEngine.glFonts.add(fntBasic = new GLFont(getCodeBase() + "Basic.glf"));
    while(gEngine.modelCount<4) sleep(100)
								

A good time to load fonts is when the models are loading. Use the glFonts.add() method to load fonts. Since loading fonts is like loading models, we should wait until all fonts are loaded before proceeding. Although there may be numerous models in a single font file, modelCount is only incremented by one for the entire collection of fonts. So, we now wait for 4 models (instead of 3 models) to load before proceeding.


    aPlayer = gEngine.addActor(mPlayer, 0, 0, -200);    // From previous lessons
    gEngine.print(fntBasic, "SCORE:", -16f, 15f, -39f);
    for(int t=0; t<6; t++)
      aScore[t] = gEngine.addGLLetter(fntBasic, 48,  -8f-((float)t/1.4f), 15f, -39f);
    addRocks(4);                                        // From previous lesson
								

Now, all we need to do is print SCORE: to the top of the display and initialize the six actors which will represent the score. Notice, that SCORE: is printed with the print() method but the score is not. That is because SCORE: remains static throughout the game but we need references to the score digits so that they may be updated at any time.


A Snippet From Basic.glf

START 046
COMPILE
USERCS
BEGIN_TRIANGLES
1 0 0 1 1 0 2 1 0
1 0 0 2 1 0 2 0 0
END
ENDLIST
START 048
COMPILE
USERCS
BEGIN_TRIANGLES
1.0 0.0 0.0 0.0 1.0 0.0 1.0 4.0 0.0
0.0 1.0 0.0 0.0 4.0 0.0 1.0 4.0 0.0
0.0 4.0 0.0 1.0 5.0 0.0 2.0 4.0 0.0
1.0 5.0 0.0 2.0 5.0 0.0 2.0 4.0 0.0
2.0 4.0 0.0 2.0 5.0 0.0 3.0 4.0 0.0
2.0 4.0 0.0 3.0 4.0 0.0 3.0 1.0 0.0
2.0 4.0 0.0 3.0 1.0 0.0 2.0 0.0 0.0
1.0 0.0 0.0 2.0 1.0 0.0 2.0 0.0 0.0
1.0 1.0 0.0 2.0 1.0 0.0 1.0 0.0 0.0
END
ENDLIST
START 049
COMPILE
USERCS
BEGIN_TRIANGLES
1.0 5.0 0.0 2.0 0.0 0.0 1.0 0.0 0.0
1.0 5.0 0.0 2.0 5.0 0.0 2.0 0.0 0.0
END
ENDLIS
								

This is a snippet from the font file, Basic.glf. It looks a lot like a glo file because it uses the glo file format to load the font models. The only difference between the glf and the glo is the START xxx keyword which specifies which ASCII character to assign to the following model. I listed my models in order. However, order is not important. The Z model can come before the A model as long as it is specified in START xxx. Finally, I would like to note the USERCS keyword. It is a valid glo keyword but are no implementations for models, just fonts. What is does is allow the color and scale to be specified at runtime. That is how my playable Asteroids can have four different colored fonts. Refer to the source code for that game to see an example of how to load a font with a different color and scale.


Asteroids

Your applet should now displays four rocks moving across the display. The player's space craft is visible, centered in the display. Pressing shift will fire bullets from the space craft. The left and right arrows will rotate the craft. The up and down arrows will provide movement and stopping and SCORE: 000000 is displayed at the top of the screen.

Copyright © 2005, Robert Walsh, All Rights reserved.