Tutorial 5 - Rendering Text
If you'd like, you can download the source for this tutorial here. See Tutorial 1 for basic engine setup.Text Renderers Are Special Objects
Each frame, the context is redrawn with the latest view of the world. Since drawing text directly to the context would be wiped out between each frame, text renderers are a special type of object. They extend from Object2D, and each renderer is a component which draws the text. The components extend from AbstractTextRenderer so they will have some basic built-in functionality. The object which does the rendering is the TextRenderer.
This tutorial is actually quite short since it's fairly easy to render text. We're going to quickly discuss each of the types of text renderer, and then show you an example of them in action. The first text renderer is the VectorText component.
Vector Text Renderer
Vector text is essentially a set of lines, connected to represent characters of the alphabet. It has a very limited character set, and only displays uppercase characters. It was originally designed for the Asteroids Clone demo game, but evolved into an engine text renderer.
Bitmap Text Renderer
The Canvas HTML element did not originally support text rendering. The Opera browser is still hindered by the fact that they haven't implemented this feature of Canvas. To get around this limitation, the BitmapText renderer was created. It has a larger character set, but still has its own limitations. Since the text is drawn as a set of bitmaps from the primary reference bitmap, it has no actual color. To achieve color, the renderer uses the composition effects of the Canvas. This is okay when nothing overlaps the text. But if something does, the color of the text will bleed into the overlapping object.
Context Native Text Renderer
Webkit and Gecko now support text rendering natively within the Canvas's context. Using this new facility, text is actually drawn by the context and the character set, and fonts, are only limited by what is available on the target machine. In even newer browsers, fonts can be downloaded from the server so that virtually any character can be represented within a game. Native text is drawn with the ContextText text renderer.
Creating the example
We load each of the text renderers, and then we also need to load the BitmapFontLoader for bitmap fonts. Bitmap fonts are essentially images with an associated descriptor file. The file indicates to the engine where characters (of a known set) begin and end.
// Load all required engine components
Engine.include("/rendercontexts/context.canvascontext.js");
Engine.include("/textrender/text.vector.js");
Engine.include("/textrender/text.bitmap.js");
Engine.include("/textrender/text.context.js");
Engine.include("/textrender/text.renderer.js");
Engine.include("/resourceloaders/loader.bitmapfont.js");
Engine.include("/engine/engine.timers.js");
In the setup() method of the game, we'll need to load the bitmap font and then make sure we wait until it has been intialized before we try to use it.
/**
* Called to set up the game, download any resources, and initialize
* the game to its running state.
*/
setup: function(){
// Set the FPS of the game
Engine.setFPS(this.engineFPS);
this.fontLoader = BitmapFontLoader.create();
this.fontLoader.load("century", "century_gothic_36.js");
// Don't start until all of the resources are loaded
var self = this;
this.loadTimeout = Timeout.create("wait", 250, function() {
self.waitForResources();
});
this.waitForResources();
},
/**
* Wait for resources to become available before starting the game
* @private
*/
waitForResources: function(){
if (this.fontLoader.isReady("century")) {
this.loadTimeout.destroy();
this.run();
return;
}
else {
// Continue waiting
this.loadTimeout.restart();
}
},
Drawing the Text
Each instance of a TextRenderer must be created with the type of render component, the text to draw, and the size of the text to draw. Additional parameters may be set on the TextRenderer to affect how the text is colored and weighted (boldness).
/**
* Run the game
*/
run: function(){
// Remove the "loading" message
$("#loading").remove();
// Create the render context
this.fieldBox = Rectangle2D.create(0, 0, this.fieldWidth, this.fieldHeight);
this.renderContext = CanvasContext.create("Playfield", this.fieldWidth,
this.fieldHeight);
this.renderContext.setBackgroundColor("#000000");
// Add the render context
Engine.getDefaultContext().add(this.renderContext);
// Vector Text
var vText = TextRenderer.create(VectorText.create(),
"Vector Text", 2.5);
vText.setPosition(Point2D.create(20, 40));
vText.setTextWeight(1);
vText.setColor("#ffffff");
this.renderContext.add(vText);
// Bitmap Text
var bText = TextRenderer.create(BitmapText.create(this.fontLoader.get("century")),
"Bitmap Text", 1.5);
bText.setPosition(Point2D.create(10, 120));
bText.setTextWeight(1);
bText.setColor("#ff0000");
this.renderContext.add(bText);
// Native Context Text
var cText = TextRenderer.create(ContextText.create(),
"Context Native Text", 2.5);
cText.setPosition(Point2D.create(10, 260));
cText.setTextFont("Verdana")
cText.setColor("#8888ff");
this.renderContext.add(cText);
},
Wrapping Up
That's it... As you can see, text isn't that difficult to draw once you know where to look and what to do. If a particular browser doesn't support native text rendering, the game doesn't throw an exception, and instead continues to run in its absence.