Better Text Drawing with Text Objects#

Screenshot of drawing with text objects

This example shows how to draw text using “text objects.” It can be many times faster than using arcade.draw_text().

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