Fast Text Drawing#

Screenshot of drawing with text objects

This example shows how to draw text using “text objects.” It is the fastest way to draw text. If you are looking for something simpler, see Slow but Easy Text Drawing.

drawing_text_objects.py#
  1"""
  2Example showing how to draw text to the screen using Text objects.
  3This is much faster than using draw_text
  4
  5If Python and Arcade are installed, this example can be run from the command line with:
  6python -m arcade.examples.drawing_text_objects
  7"""
  8from __future__ import annotations
  9
 10import arcade
 11
 12SCREEN_WIDTH = 1200
 13SCREEN_HEIGHT = 800
 14SCREEN_TITLE = "Drawing Text Example"
 15DEFAULT_LINE_HEIGHT = 45
 16DEFAULT_FONT_SIZE = 20
 17
 18
 19class MyGame(arcade.Window):
 20    """
 21    Main application class.
 22    """
 23
 24    def __init__(self, width, height, title):
 25        super().__init__(width, height, title)
 26
 27        self.background_color = arcade.color.BEIGE
 28        self.text_angle = 0
 29        self.time_elapsed = 0.0
 30
 31        # Add the screen title
 32        start_x = 0
 33        start_y = SCREEN_HEIGHT - DEFAULT_LINE_HEIGHT * 1.5
 34        self.title = arcade.Text(
 35            "Text Drawing Examples",
 36            start_x,
 37            start_y,
 38            arcade.color.BLACK,
 39            DEFAULT_FONT_SIZE * 2,
 40            width=SCREEN_WIDTH,
 41            align="center",
 42        )
 43
 44        # start_x and start_y make the start point for the text. We draw a dot to make it
 45        # easy to see the text in relation to its start x and y.
 46        start_x = 10
 47        start_y = SCREEN_HEIGHT - DEFAULT_LINE_HEIGHT * 3
 48        self.fonts = arcade.Text(
 49            "Fonts:",
 50            start_x,
 51            start_y,
 52            arcade.color.FRENCH_WINE,
 53            DEFAULT_FONT_SIZE, bold=True,
 54        )
 55
 56        # Move the y value down to create another line of text
 57        start_y -= DEFAULT_LINE_HEIGHT
 58        self.font_default = arcade.Text(
 59            "Default Font (Arial)",
 60            start_x,
 61            start_y,
 62            arcade.color.BLACK,
 63            DEFAULT_FONT_SIZE
 64        )
 65
 66        # Show some built-in fonts
 67        start_y -= DEFAULT_LINE_HEIGHT
 68        self.font_kenney_blocks = arcade.Text(
 69            "Kenney Blocks Font",
 70            start_x,
 71            start_y,
 72            arcade.color.BLACK,
 73            DEFAULT_FONT_SIZE,
 74            font_name="Kenney Blocks",
 75        )
 76
 77        start_y -= DEFAULT_LINE_HEIGHT
 78        self.font_kenney_future = arcade.Text(
 79            "Kenney Future Font",
 80            start_x,
 81            start_y,
 82            arcade.color.BLACK,
 83            DEFAULT_FONT_SIZE,
 84            font_name="Kenney Future",
 85        )
 86
 87        start_y -= DEFAULT_LINE_HEIGHT
 88        self.font_kenney_high = arcade.Text(
 89            "Kenney High Font",
 90            start_x,
 91            start_y,
 92            arcade.color.BLACK,
 93            DEFAULT_FONT_SIZE,
 94            font_name="Kenney High"
 95        )
 96
 97        start_y -= DEFAULT_LINE_HEIGHT
 98        self.font_kenney_high_square = arcade.Text(
 99            "Kenney High Square Font",
100            start_x,
101            start_y,
102            arcade.color.BLACK,
103            DEFAULT_FONT_SIZE,
104            font_name="Kenney High Square",
105        )
106
107        start_y -= DEFAULT_LINE_HEIGHT
108        self.font_kenney_mini_square = arcade.Text(
109            "Kenney Mini Square Font",
110            start_x, start_y,
111            arcade.color.BLACK,
112            DEFAULT_FONT_SIZE,
113            font_name="Kenney Mini Square",
114        )
115
116        start_y -= DEFAULT_LINE_HEIGHT
117        self.font_kenney_pixel = arcade.Text(
118            "Kenney Pixel Font",
119            start_x, start_y,
120            arcade.color.BLACK,
121            DEFAULT_FONT_SIZE,
122            font_name="Kenney Pixel",
123        )
124
125        start_y -= DEFAULT_LINE_HEIGHT
126        self.font_kenney_pixel_square = arcade.Text(
127            "Kenney Pixel Square Font",
128            start_x, start_y,
129            arcade.color.BLACK,
130            DEFAULT_FONT_SIZE,
131            font_name="Kenney Pixel Square",
132        )
133
134        start_y -= DEFAULT_LINE_HEIGHT
135        self.font_kenney_rocket = arcade.Text(
136            "Kenney Rocket Font",
137            start_x, start_y,
138            arcade.color.BLACK,
139            DEFAULT_FONT_SIZE,
140            font_name="Kenney Rocket",
141        )
142
143        start_y -= DEFAULT_LINE_HEIGHT
144        self.font_kenney_rocket_square = arcade.Text(
145            "Kenney Rocket Square Font",
146            start_x, start_y,
147            arcade.color.BLACK,
148            DEFAULT_FONT_SIZE,
149            font_name="Kenney Rocket Square",
150        )
151
152        start_y -= DEFAULT_LINE_HEIGHT
153        # When trying to use system fonts, it can be risky to specify
154        # only a single font because someone else's computer might not
155        # have it installed. This is especially true if they run a
156        # different operating system. For example, if you are on Windows
157        # and a friend has a mac or Linux, they might not have the same
158        # fonts. Your game could look different or broken on their computer.
159        # One way around that is to provide multiple options for draw_text
160        # to try. It will use the first one it finds, and use Arial as a
161        # default if it can't find any of them.
162        # In the example below, draw_text is given a tuple of names for very
163        # similar fonts, each of which is common on a different major
164        # operating systems.
165        self.font_times_new_roman = arcade.Text(
166            "Times New Roman (Or closest match on system)",
167            start_x, start_y,
168            arcade.color.BLACK,
169            DEFAULT_FONT_SIZE,
170            font_name=(
171                "Times New Roman",  # Comes with Windows
172                "Times",  # MacOS may sometimes have this variant
173                "Liberation Serif"  # Common on Linux systems
174            )
175        )
176
177        start_y -= DEFAULT_LINE_HEIGHT
178        self.multi_line_breaks = arcade.Text(
179            "Multi-Line\ntext using\n\\n characters.",
180            start_x, start_y,
181            arcade.color.BLACK,
182            DEFAULT_FONT_SIZE / 2,
183            multiline=True,
184            width=300,
185        )
186
187        start_y -= DEFAULT_LINE_HEIGHT * 1.5
188        self.multiline_wrap = arcade.Text(
189            "Wrapping really long text automatically to a new line. "
190            "The quick brown fox jumped over the lazy dogs.",
191            start_x,
192            start_y,
193            arcade.color.BLACK,
194            DEFAULT_FONT_SIZE / 2,
195            multiline=True,
196            width=300
197        )
198
199        # --- Column 2 ---
200        start_x = 750
201        start_y = SCREEN_HEIGHT - DEFAULT_LINE_HEIGHT * 3
202        self.text_positioning = arcade.Text(
203            "Text Positioning:",
204            start_x,
205            start_y,
206            arcade.color.FRENCH_WINE,
207            DEFAULT_FONT_SIZE,
208            bold=True,
209        )
210
211        # start_x and start_y make the start point for the text.
212        # We draw a dot to make it easy to see the text in relation to
213        # its start x and y.
214        start_y -= DEFAULT_LINE_HEIGHT
215
216        self.default_baseline_left = arcade.Text(
217            "Default of 'baseline' and 'Left'",
218            start_x,
219            start_y,
220            arcade.color.BLACK,
221            DEFAULT_FONT_SIZE,
222        )
223
224        start_y -= DEFAULT_LINE_HEIGHT
225        self.bottom_left = arcade.Text(
226            "'bottom' and 'left'",
227            start_x,
228            start_y,
229            arcade.color.BLACK,
230            DEFAULT_FONT_SIZE,
231            anchor_x="left",
232            anchor_y="bottom",
233        )
234
235        start_y -= DEFAULT_LINE_HEIGHT
236        self.top_left = arcade.Text(
237            "'top' and 'left'",
238            start_x, start_y,
239            arcade.color.BLACK,
240            DEFAULT_FONT_SIZE,
241            anchor_x="left",
242            anchor_y="top",
243        )
244
245        start_y -= DEFAULT_LINE_HEIGHT * 2
246        self.basline_center = arcade.Text(
247            "'baseline' and 'center'",
248            start_x, start_y,
249            arcade.color.BLACK,
250            DEFAULT_FONT_SIZE,
251            anchor_x="center",
252            anchor_y="baseline",
253        )
254
255        start_y -= DEFAULT_LINE_HEIGHT
256        self.baseline_right = arcade.Text(
257            "'baseline' and 'right'",
258            start_x,
259            start_y,
260            arcade.color.BLACK,
261            DEFAULT_FONT_SIZE,
262            anchor_x="right",
263            anchor_y="baseline",
264        )
265
266        start_y -= DEFAULT_LINE_HEIGHT
267        self.center_center = arcade.Text(
268            "'center' and 'center'",
269            start_x,
270            start_y,
271            arcade.color.BLACK,
272            DEFAULT_FONT_SIZE,
273            anchor_x="center",
274            anchor_y="center",
275        )
276
277        start_y -= DEFAULT_LINE_HEIGHT * 4
278        # start_x = 0
279        # start_y = 0
280        self.rotating_text = arcade.Text(
281            "Rotating Text",
282            start_x, start_y,
283            arcade.color.BLACK,
284            DEFAULT_FONT_SIZE,
285            anchor_x="center",
286            anchor_y="center",
287            rotation=self.text_angle
288        )
289
290    def on_update(self, delta_time):
291        self.text_angle += 1
292        self.time_elapsed += delta_time
293
294    def on_draw(self):
295        """
296        Render the screen.
297        """
298        # This command should happen before we start drawing. It will clear
299        # the screen to the background color, and erase what we drew last frame.
300        self.clear()
301
302        # Draw all the text objects
303        # Column 1
304        self.title.draw()
305        self.fonts.draw()
306        self.font_default.draw()
307        self.font_kenney_blocks.draw()
308        self.font_kenney_future.draw()
309        self.font_kenney_high.draw()
310        self.font_kenney_high_square.draw()
311        self.font_kenney_mini_square.draw()
312        self.font_kenney_pixel.draw()
313        self.font_kenney_pixel_square.draw()
314        self.font_kenney_rocket.draw()
315        self.font_kenney_rocket_square.draw()
316        self.font_times_new_roman.draw()
317        self.multi_line_breaks.draw()
318        self.multiline_wrap.draw()
319
320        # Column 2
321        self.text_positioning.draw()
322
323        arcade.draw_point(
324            self.default_baseline_left.x,
325            self.default_baseline_left.y,
326            arcade.color.BARN_RED,
327            5,
328        )
329        self.default_baseline_left.draw()
330
331        arcade.draw_point(
332            self.bottom_left.x,
333            self.bottom_left.y,
334            arcade.color.BARN_RED,
335            5,
336        )
337        self.bottom_left.draw()
338
339        arcade.draw_point(
340            self.top_left.x,
341            self.top_left.y,
342            arcade.color.BARN_RED,
343            5,
344        )
345        self.top_left.draw()
346
347        arcade.draw_point(
348            self.basline_center.x,
349            self.basline_center.y,
350            arcade.color.BARN_RED,
351            5
352        )
353        self.basline_center.draw()
354
355        arcade.draw_point(
356            self.baseline_right.x,
357            self.baseline_right.y,
358            arcade.color.BARN_RED,
359            5,
360        )
361        self.baseline_right.draw()
362
363        arcade.draw_point(
364            self.center_center.x,
365            self.center_center.y,
366            arcade.color.BARN_RED,
367            5,
368        )
369        self.center_center.draw()
370
371        arcade.draw_point(
372            self.rotating_text.x,
373            self.rotating_text.y,
374            arcade.color.BARN_RED,
375            5,
376        )
377        self.rotating_text.rotation = self.text_angle
378        self.rotating_text.draw()
379
380
381def main():
382    MyGame(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE)
383    arcade.run()
384
385
386if __name__ == "__main__":
387    main()