Buttons and sliders

Workshop 07: Strings, texts and fonts

We have learned how to display panels, digits and a lot of great looking panel elements. If we need to display a text (the name of the player, a message, etc) we have to use strings and texts. And if we want our texts to stand out of the crowd, we need to use good looking fonts. In this lesson we'll also learn how to dynamically change panels, texts, or anything else during gameplay.

Strings

A string is a sequence of characters: letters, numbers, symbols. Here are a few string examples:

STRING player_str = "Johnny Bravo";
STRING my_very_own_string = "I'm even cooler than the coolest!"
STRING player_meets_monster = "Die now! I won't have time for that later!";
STRING crypto1234 = "a#45@123--//";
STRING test_string; // empty, unlimited string
STRING riddle = "#100"; // empty string, can store up to 100 characters

We can learn a few things just by looking at the definitions above:

1. Every string must be defined before being used, using the keyword "STRING".

2. The content of the string (if any) must be given between quotation marks.

3. We can assign a sequence of characters to our strings as we define them or we can create empty strings that will be filled with characters later.

4. A string can have an unlimited length or a specified length; STRING riddle = "#100"; creates a string named riddle that can store up to 100 characters. Tip: In old scripts you'll often also find definitions like STRING riddle[100]; for specified length strings.

5. Every C-Script line needs to end with a semicolon; don't forget the semicolon at the end of your string definitions.

6. The same naming conventions that are used for variables apply for string names. I like to add _str to my strings but you don't need to do that.

The strings can't display anything on the screen by themselves; they need to be placed inside a text definition.
 

Texts

A text is an object that can display one or several strings on the screen. Here's a simple text definition:

TEXT first_txt
{
    pos_x = 300;
    pos_y = 250;
    layer = 3;

    font = some_font; // previously defined font
    string = player_str;
    flags = VISIBLE;
}

It looks a lot like a panel, doesn't it? The good news is that its definition is really simple:
- pos_x and pos_y give the distance (in pixels) to the upper left corner of the screen;
- layer determines which elements on the screen are covered by the text;

- font gives the name of the previously defined FONT that will be used for the text. If it's omitted, our _a4font will be used;
- string gives a string that will be displayed. Just like with BMAPs and PANELs, you can either give the name of a previously defined string, or directly enter a string in quotes;
- flags = VISIBLE makes the text visible.

It really is simple! I can't wait to see a text on the screen!

Open script07 - it should look like this:

////////////////////////////////////////////////////////////////////

STRING aloha_str = "Welcome to Paradise Island!";

////////////////////////////////////////////////////////////////////

TEXT greetings_txt
{
	pos_x = 300;
	pos_y = 250;
	string = aloha_str;
	flags = VISIBLE;
}

////////////////////////////////////////////////////////////////////  

You can see that we have defined a string named aloha_str:

STRING aloha_str = "Welcome to Paradise Island!";

Don't forget that you can put anything else (characters, numbers, symbols) between those quotation marks. Our text definition is really simple; let's run our script file!

Dynamically changing objects

Time to learn something new; let's add the line below at the beginning of our script07 file:

STRING pockets_str = "We will try to empty your pockets!";

and then let's add a function main to make it look this way:

function main()
{
    wait (-3);
    greetings_txt.string = pockets_str;
    wait (-3);
    greetings_txt.visible = OFF;
}

Your script file should look like this (green = new lines of code):

////////////////////////////////////////////////////////////////////

STRING aloha_str = "Welcome to Paradise Island!";
STRING pockets_str = "We will try to empty your pockets!"; 

////////////////////////////////////////////////////////////////////

TEXT greetings_txt
{
	pos_x = 300;
	pos_y = 250;
	string = aloha_str;
	flags = VISIBLE;
}

////////////////////////////////////////////////////////////////////

function main() 
{ 
  wait (-3); 
  greetings_txt.string = pockets_str; 
  wait (-3); 
  greetings_txt.visible = OFF; 
}  

Run the script07 file again and you will see the following sequence:

  

The code that does all these things is located inside function main(), so let's discuss it right away:

function main()
{
    wait (-3);
    greetings_txt.string = pockets_str;
    wait (-3);
    greetings_txt.visible = OFF;
}

wait(-3); is a predefined engine function that instructs the engine to wait for 3 seconds. After that we have this weird looking line of code:

greetings_txt.string = pockets_str;

Pay attention because this could be the most important phrase I've written so far: we can access (almost) any property / feature for an object, like a text, using the "dot method" as shown below:

object.property

We have used this dot method in the first workshop, when we have typed camera.arc = ... with camera being the object and arc being one of its properties. You can see the predefined objects and their properties in the second part of the manual. Now that we know about the dot method, that weird line of code isn't looking that frightening. We have the object named greetings_txt and we set one of its properties (its string) to be equal to the previously defined string named pockets_str. This way we get to display a different string using the same text definition.

If you are wondering what else could be changed to this text using the dot method, the answer is simple: almost everything! Let's take a look at the text definition again:

TEXT greetings_txt
{
    pos_x = 300;
    pos_y = 250;
    string = aloha_str;
    flags = VISIBLE;
}

We could use greetings_txt.pos_x = 500; and the text will be placed 500 pixels away from the left side of the screen; we already know how to change the string for this text and we can use greetings_txt.visible = OFF; to hide the text completely. These lines of code should be placed in function main, or maybe inside one of your own functions, maybe inside a function that runs when you click a button! Can you do that for me, please?

You can use the dot method to control panels, texts, entities (be patient, we will get there too)... Ok, I'll give you a few more examples:

display_pan.visible = OFF; // hides the panel named display_pan
test_pan.visible = ON; // shows the panel named test_pan if it was hidden
hi_txt.string = newstring_str; // gives hi_txt a new string
error_pan.pos_y = 300; // sets a new pos_y value for the panel named error_pan

You might have noticed that my text definition doesn't include a font = some_font; line of code. If you forget to do that, the engine will use the internal _a4font and this is what happened here. You'd like to use a new font, wouldn't you?
 

Fonts

A font is a set of characters that can be used for our texts. The engine can use two types of fonts:
- true type fonts, just like the ones used by Windows;
- bitmap fonts; a set of characters that is read from a bitmap file.

True type fonts

You have many true type fonts installed on your pc; open the folder named \fonts inside your windows folder and you should see them:

If you double click a font you will see its full set of characters, as well as some text samples:

This is your regular true type font and you can see that the characters aren't forced to have a fixed width: "i" is much thinner than "m". Let's see a true type font definition:

FONT my_font_name = "font_name_in_windows", font_type, character_height; // true type font

- my_font_name is the name chosen by you for the font, for example arial_font;
- font_name_in_windows is the name of the font as it appears in Windows' \fonts folder. You can use "Arial", "Times" (Times New Roman) and "Courier" here; these fonts are guaranteed to be present in any PC that runs Windows;
- font_type can be 0 (normal), 1 (bold), 2 (italic), 3 (bold + italic), just like in your word processor;
- character_height is the height of the font character in points, just like in your word processor.

And now let's see a true type font example:

FONT arial_font = "Arial", 1, 20; // Arial, bold, a character has a height of 20 points
 

Bitmap fonts

If you choose to use a bitmap font, "i" and "m" will have the same width, so your text will look something like this:

Those red squares will not appear on the screen; I drew them because I wanted you to see that all the characters have the same width. Take another look at the same text, this time without the red squares:

Let's see a bitmap font definition:

FONT my_font_name = "bitmap_name", character_width, character_height; // fixed width font

- my_font_name is the name chosen by you for the font, for example adventure_font;
- bitmap_name is the name of the bitmap used for the font;
- character_width is the width of the character (remember that all the characters have the same width);
- character_height is the height of the character.

Let's see a bitmap font example:

FONT adventure_font = "adventure.pcx", 20, 15; // uses a bitmap named adventure.pcx, a character has 20x15 pixels.

Everything looks nice but what is it with that bitmap? Well, if you are going to use a bitmap font you will have to create all the characters for it by yourself. You create a black (RGB = 000) rectangle and you draw your characters inside it. The sequence of alphanumerical characters in the bitmap must correspond to the character set used by the script. Here's an example (you can ignore the small red rectangles or you can add other characters to the font):

There should be 32 characters per row, ordered in four rows (32 characters x 4 rows = 128 characters in my example) or in eight rows (256 characters). If you don't plan to use letters, you can create a smaller font bitmap that looks like this (11 characters x 1 row, contains 0...9 and space):

Important note: the bitmap must have exactly 11 times (11 x 1), 128 times (32 x 4) or 256 times (32 x 8) the given character size. If you don't respect this rule you will fail to create a usable font.

The bitmaps for those fixed width fonts are pretty hard to create, aren't they? Before you start pulling your hair off, you can find a "font generator" tool at Conitec's "Links" page. Choose the name of the font, set its size and press a button to generate the bitmap automatically.

Let's see some pros and cons for these two types of fonts:
Font Creation Pros Cons Other
True Type No need to Variable width Single color Only a few true type fonts (Arial, Times, Courier)
are installed on all the PCs in this world.
Bitmap Time consuming Multicolored Fixed width Can be used to display all kinds of symbols
(like alien alphabets).

So what type of font are you going to use? Will it be a true type font or a bitmap font? The texts look really good if you use a true type font but you can't afford to use a font that isn't installed on all the PCs. A bitmap font can be displayed on any pc because you will distribute the bitmap together with your game.

Let's see how these fonts look and then you should be able to choose the best type of font for your projects; I encourage you to use both types for the same project if you need to.

Start SED and load the script07_2 file:

////////////////////////////////////////////////////////////////////

STRING test_str = "I like to write programs!";

////////////////////////////////////////////////////////////////////

FONT system_font = "system.pcx", 10, 12; // bitmap, 10 x 12 pixels for a character
FONT arial_font = "Arial", 1, 18; // true type, Arial, bold, size = 18

////////////////////////////////////////////////////////////////////

TEXT fixed_width_txt
{
	pos_x = 200;
	pos_y = 250;
	font = system_font;
	string = test_str;
	flags = VISIBLE;
}

TEXT true_type_txt
{
	pos_x = 200;
	pos_y = 280;
	font = arial_font;
	string = test_str;
	flags = VISIBLE;
}

////////////////////////////////////////////////////////////////////

This script includes two font definitions and two texts that use different fonts and the same test_str string. Let's run the script7_2 script:

I wouldn't blame you if you want to see how this system.pcx bitmap looks like; you can find it and open it inside the \workshop07 folder (where else could it be?) or you can take a look at its picture below:

  system.pcx= the bitmap used for the bitmap font
 
I have told you that the engine won't care if you don't paint nice figures and letters on the font; you can use texts and digits to display pictures, weird symbols and so on. Here's an example from one of Alain Brégeon's multiplayer workshops that can be downloaded from Conitec's homepage:

If the font would be named icons.bmp, its definition would look like this:

FONT icons_font = "icons.bmp", 18, 30;

Let's define a panel that uses this font and a digit:

PANEL some_pan
{
      pos_x = 0;
      pos_y = 0;
      digits (410, 200, 1, icons_font, 1, picture);
      flags = OVERLAY, VISIBLE;
}

If the variable named picture is 2, the digit will display a white rocket; if picture is 3 we will see a little red heart. If picture is 4 we will see the red rocket and so on, get it? You could replace the pictures with any other weird symbols to create an alien alphabet or stuff like that.

Ready for a new challenge? Try to write the code that switches the fonts for the two texts, three seconds after the level is loaded, like below:

  three seconds later.... 

Solution: add a 3 lines function main:

function main()
{
     wait(-3); // wait for 3 seconds
     fixed_width_txt.font = arial_font; // switch the fonts
     true_type_txt.font = system_font; // for the 2 texts
}

Next: Position, angle and scale