Game Development Community

Text On The Screen

by David Taylor · in Torque Game Builder · 04/24/2006 (6:34 pm) · 17 replies

How is text drawn to the screen? I'd like to draw text to the screen using a font page. Can anyone advise me how to go about this? I'm assuming I'll need to know the dimensions and locations of each letter on the font page, but where to go from there is a mystery, lol! :/

#1
04/25/2006 (12:12 am)
Depends what you want to do really. If you want simple text, you could set up a GUI, define your fonts and point sizes in a cusotm profile, and then just update the GUI control with the text you want to display.

If you want to use bitmap fonts so you get all the spangly effects that go along with using imagemaps it's a little more complicted.

David Grace released a bitmap font resource for an older version of TGB that requires an engine recompile, but I don't know if it will work with the current version.
#2
04/25/2006 (12:49 am)
How does updating the GUI control work, Philip? And is it possible to use custom fonts that way?
#3
04/25/2006 (1:26 am)
Add the following to your .gui file
new GuiTextCtrl(lblScoreText) {
      profile = "scoreTextProfile";
      horizSizing = "right";
      vertSizing = "bottom";
      position = "34 8";
      extent = "131 36";
      minExtent = "8 2";
      visible = "1";
      text = "Score: 0";
      maxLength = "255";
   };

Then create in one of your game .cs files add:
new GuiControlProfile (ScoreTextProfile)
{
   fontType = "Gigi";
   fontSize = 20
   fontColor = "255 0 0";
   fixedExtent = true;
   justify = "left";
};

Finally, when you need to update the text, use:
lblScoreText.setText( "Score:" SPC $playerScore);

That should sort you out. The only thing to watch is that you will need to create a new profile for each point size/colour of text that you want to use.

I tend to call my profiles things like: Gigi20Red, Arial12Blue and so-on, so I know what font, point size and colour the text will be rendered in.
#4
04/30/2006 (8:49 pm)
Thanks for that, Philip, but I'm getting an error trying to setText() - I can't find that function anywhere in the reference.pdf, either.

The error says: "Unknown command setText. Object TextOneGui (1849) GuiControlProfile -> SimObject".
#5
04/30/2006 (9:03 pm)
Looks like you're calling setText on the profile and not the guiTextCtrl object.
#6
04/30/2006 (10:14 pm)
Thanks, Matthew. I'm not getting the error any more, but I'm not seeing any text, either, lol. I've used the exact same code as Philip has suggested, but nothing is coming up on the screen.
#7
05/01/2006 (10:07 am)
@David

After you created your GUI, did you display it with a Canvas.setContent call? If not, that might be why it isn't visible ;)
#8
05/01/2006 (12:14 pm)
Ah, that's what I was missing. Many thanks! :)
#9
05/02/2006 (12:09 am)
That's making the game freeze now...very odd...

When there is a collision, I call setText(), and it displays the text, but everything then freezes. Does anyone know what might be causing this, and how to rectify it so that the text still draws but everything else continues on, too?

function t2dSceneObject::onCollision( %srcObj, %dstObj, %srcRef, %dstRef, %time, %normal,
%contactCount, %contacts )
{
    displayText(lblScoreText, "Marble Hit!");
    echo("Hit!");
}

function displayText(%font, %text)
{
    %font.setText(%text);
    canvas.SetContent(%font);
}
#10
05/02/2006 (10:03 am)
By using setContent on the canvas, I think you're completely replacing everything else that the canvas was displaying. Instead, you want to either push the dialog on top of the other items already on the canvas, with:

function displayText(%font, %text)
{
   %font.setText(%text);
   canvas.pushDialog(%font);
}

Or add it to the existing GUI on the fly, with something like:

function displayText(%font, %text)
{
   %font.setText(%text);
   Canvas.getContent().add(%font);
}

The first method is adding an entirely new GUI to the canvas. The nice thing about this is it stays independent of other GUIs, you can cleanly and easily .push it on and then .pop it off to get rid of it, etc. One feature that also tends to cause trouble is that by default GUIs are modal. If you .push() a new one on top of the existing GUI elements (such as the one that likely contains your game window) then your mouse/keyboard input gets consumed by the new GUI and never get down to your game. To fix this, you need to make the GUI modeless, by defining "modal = false;" in the profile you assign to your GUI when you define it.

The second avoids this problem by making the text be an actual component of the currently active GUI. This is simple and effective, and avoids the modal/modeless issue entirely. However you lose some of the flexibility of having it as a separate GUI, which may or may not be important to you depending on your needs.
#11
05/02/2006 (6:56 pm)
Thanks, Luke. I've implemented the first method, as flexibility of a separate GUI is important to me. And, just as you said, mouse input seems to stop. The marbles collide, the text writes to the screen, and the marbles continue to move, but the mouse no longer moves the hand sprite (a sprite that moves in response to an onMouseMove() call).

However, adding "modal = false;" doesn't affect that at all. Unless I've done it wrong? Though I can't think how that could be...

new GuiControlProfile (ScoreTextProfile)
    {
        fontType = "Gigi";
        fontSize = 20;
        fontColor = "255 0 0";
        fixedExtent = true;
        justify = "left";
        modal = "false";
    };

Interestingly, though, if there is a collision, and the mouse has stopped working, and I then press F10 to access the GUI editor, returning to the game allows my mouse to move. Odd, no?
#12
05/02/2006 (7:19 pm)
I also just noticed that changinge fontColor to "255 255 255" has had no effect on the font, either. The text IS being called, because I have echo commands either side of it that reveal the code is being hit there. Any ideas why what I'm putting in the GuiControlProfile is having no effect?
#13
05/02/2006 (7:23 pm)
Do you have the Score GuiTextCtrl as a child object of another GuiControl of some kind? If so, that'll need to use a profile that has the modal=false parameter. So for example if you had:

new GuiControl(testGui) {
   profile = "GuiDefaultProfile";
   horizSizing = "right";
   vertSizing = "bottom";
   position = "0 0";
   extent = "800 600";
   minExtent = "8 2";
   visible = "1";

   new GuiTextCtrl(testGuiScoreText) {
	profile = "TestScoreTextProfile";
	horizSizing = "center";
	vertSizing = "center";
	position = "0 275";
	extent = "800 56";
	minExtent = "8 2";
	visible = "1";
	text = "Test Test...";
	maxLength = "255";
   };
};

Then the parent gui control would need to be modeless, not the text ctrl. Here's what I used to make sure it can work just now:

new GuiControlProfile (TestScoreTextProfile)    
{
	fontType = "Arial";
	fontSize = 20;
	fontColor = "255 0 0";
	fixedExtent = true;
	justify = "left";
	modal = "false";
};


new GuiTextCtrl(testGui) {
	profile = "TestScoreTextProfile";
	horizSizing = "center";
	vertSizing = "center";
	position = "0 275";
	extent = "800 56";
	minExtent = "8 2";
	visible = "1";
	text = "Test Test...";
	maxLength = "255";
};

I put this in its own file that gets loaded at startup. I then ran the game which has a scenewindow with a sprite controlled by the mouse, and did "Canvas.pushDialog(testGui);" at the console. The text pops up but the mouse still works.
#14
05/02/2006 (7:24 pm)
If changing something else isn't working, are you certain the script file is getting compiled, and it isn't falling back to an old version because of a syntax error?
#15
05/02/2006 (7:48 pm)
I didn't previously have a parent gui, but now that I do, it all works fine. Thanks heaps. :)

One more question - is there any way to modify the text location within the script itself, (not the gui file)? For example, I'd like to be able to get the text to write "Hit!" where the marbles actually collide, no matter where that might be on the screen.

Thanks so much for figuring all of this out, Luke! :)
#16
05/02/2006 (9:26 pm)
You can call .setPosition(x, y); on a Gui control. Also, x and y are in screen coordinates, not t2d coordinates.
#17
05/03/2006 (8:46 pm)
Unfortunately, that isn't changing the location of the text for me. The only thing that seems to change its location is if I change justify = "left"; to 'justify = "center";'. Then it is in the absolute center of the screen.

function t2dSceneObject::onCollision( %srcObj, %dstObj, %srcRef, %dstRef, %time, %normal,
%contactCount, %contacts )
{
    displayText(testGui, "Marble Hit!!!");
    echo("Hit!");
}

function displayText(%font, %text)
{
    %font.setText(%text);
    %font.setPosition(1, 1);
    canvas.pushDialog(%font);
}