Part 7: Drawing text¶
In this chapter we’ll lear how to draw text in the game
Loading fonts from files¶
In order to draw a text, we must first load a font from a file. Like with images or sounds, it’s very easy:
from kaa.fonts import Font
my_font = Font('/path/to/font.ttf')
Font formats currently supported by kaa:
ttf
Drawing text¶
To draw a text, create a TextNode
and add it to the scene. TextNode
extends
basic Node
and therefore inherits all its properties - position, rotation, scale, color, origin_alignment etc.
It adds the following new properties:
font
- A font to use when rendering text. Pass aFont
instance.text
- a string. A text you want to draw.font_size
- an integer. Size of the text.line_width
- an integer. Width of the text, in pixels. If set, the text will wrap automatically to fit this width. If not set, text won’t wrap.interline_spacing
- an integer. Space between lines of text in pixels. Used when the text wraps (due to line_width).first_line_indent
- an integer. Indentation for the first line. Useful when you have multiple line texts (due to line_width)
Full example¶
Let’s load a font from file and add some texts in the game.
from kaa.fonts import Font
class AssetsController:
def __init__(self):
# ... the rest of the function .....
# Load all fonts
self.font_1 = Font(os.path.join('assets', 'fonts', 'paladise-script.ttf'))
self.font_2 = Font(os.path.join('assets', 'fonts', 'DejaVuSans.ttf'))
import registry
import settings
from kaa.geometry import Vector, Alignment
from kaa.fonts import TextNode
from kaa.colors import Color
class GameplayScene(Scene):
def __init__(self):
super().__init__()
self.frag_count = 0
self.root.add_child(TextNode(font=registry.global_controllers.assets_controller.font_1,
origin_alignment=Alignment.left, position=Vector(10, 20), font_size=40, z_index=1,
text="WASD to move, mouse to rotate, left mouse button to shoot"))
self.root.add_child(TextNode(font=registry.global_controllers.assets_controller.font_1,
origin_alignment=Alignment.left, position=Vector(10, 45), font_size=40, z_index=1,
text="1, 2, 3 - change weapons. SPACE - spawn enemy"))
self.root.add_child(TextNode(font=registry.global_controllers.assets_controller.font_2,
origin_alignment=Alignment.right, position=Vector(1910, 20), font_size=30, z_index=1,
color=Color(1, 0, 0, 1), text="Press Q to quit game"))
self.frag_count_label = TextNode(font=registry.global_controllers.assets_controller.font_1,
origin_alignment=Alignment.left, position=Vector(10, 70), font_size=40, z_index=1,
color=Color(1, 1, 0, 1), text="")
self.root.add_child(self.frag_count_label)
# .... rest of the code
def score_frag(self):
# function for tracking frag count
self.frag_count += 1
self.frag_count_label.text = f"Frag Count: {self.frag_count}"
Run the game and check out the results!
Note
When adding TextNode
to the scene it’s important to give them proper z_index
. Games will usually
have some background image and you may often be wondering “why is that TextNode not visible”? Most likely it’s
because of z_index
being too low and some other sprite is rendering in front of it!
Updating text¶
Updating text property of the TextNode
is a performance-heavy operation and you should avoid updating
text
property on each frame (unless it’s really needed). In our case, we only need to update
the frag count when an enemy is killed. We’ve already written a score_frag
function, let’s now call it:
class EnemiesController:
def remove_enemy(self, enemy):
self.enemies.remove(enemy) # remove from the internal list
enemy.delete() # remove from the scene
# increment the frag counter
self.scene.score_frag()
Transforming text¶
Since text nodes are regular Nodes, you can use all of base Node
properties to transform them, e.g. reposition,
rotate, scale, etc.
my_text_node.rotation_degrees = 45
my_text_node.scale = Vector(0.5, 0.75)
Text Nodes can also be a child nodes of other nodes, and can have child nodes themselves.
tn = TextNode(font = my_font, text="Hello world")
tn.add_child(Node(sprite=my_sprite))
Let’s move on, to the next part of the tutorial