Work with text¶
In pygame, text cannot be written directly to the screen. The first step is to create a Font object with a given font size. The second step is to render the text into an image with a given color. The third step is to blit the image to the screen. These are the steps:
Once the font is created, its size cannot be changed. A Font object is used to create a Surface object from a string. Pygame does not provide a direct way to write text onto a Surface object. The method render() must be used to create a Surface object from the text, which then can be blit to the screen. The method render() can only render single lines. A newline character is not rendered.
Initialize a font¶
Initializing the font can take a few seconds. On a MacBook Air the the creation of a system Font object:
took more then 8 seconds:
The function get_fonts() returns a list of all installed fonts. The following code checks what fonts are on your system and how many, and prints them to the console:
You will get something like this:
Render the text¶
The font object can render a given text into an image. In the example below, we place a blue bounding rectangle around that text image:
We then create two more fonts, Chalkduster and Didot at a size of 72 points. We render a text with both fonts:
Finally the text images are blit to the screen like regular images:
This is the result:
Here is the full code.
Edit text with the keybord¶
The keyboard event can be used to edit a text. First we create a text which we save in a string variable text and which we render to an image:
Then we define the bounding rectangle and furthermore a cursor rectangle which is juxtaposed to the text bounding rectangle:
Inside the event loop we watch out for KEYDOWN events. If the key press is a BACKSPACE and the lenght of the string is larger than 0, then we remove the last character, else we append the new character to the text variable:
Then we render the modified text, update the bounding rectangle, and place the cursor box at the end of the updated bounding rectangle:
How to display text in pygame? [duplicate]
I can’t figure out to display text in pygame.
I know I can’t use print like in regular Python IDLE but I don’t know how.
This is only the beginning part of the whole program.
If there is a format that will allow me to show the text I type in the pygame window that’d be great. So instead of using print I would use something else. But I don’t know what that something else is. When I run my program in pygame it doesn’t show anything.
I want the program to run in the pygame window instead of it just running in idle.
Pygame tutorial #1: displaying rendered text in a window.
Recently I had an idea to create a story-based game using python and pygame library. So I decided it’d be worth giving it a shot.
First things first, let’s import the stuff that we need for now.
Now, let’s configure all the necessary stuff.
The set.caption() function changes the window’s name. You could name the window anything you want.
Firstly, we need to create a font renderer that renders text with specific font and size. But creating a rendered font requires 2 things: the font that we need, and the size of the text.
The problem with passing the first thing to the font renderer is that you need to pass the string of the entire path to the font. It is time-consuming to manually search for the fonts you need, so Pygame offers a simple function: font.match_font() , which returns the path to the font, given the font’s name.
Pygame also offers a function that returns a list of available fonts: font.get_fonts() . Try running this in your shell to see all available fonts:
Usually when running this function, it randomly shuffles the list, so I strongly discourage getting fonts from this list via index.
Now that we settled the question, let’s create the font renderer.
Now let’s try to render the message with our rendered font, and color (with a XY position of 5, 500)
This is how it should look like:
This is not a really convenient way to render messages, but at least it renders it now! Let’s simplify this even more:
We can simplify it even more!
Let’s remove the font renderer function and write the message display as a one big function.
At this point the function looks much simpler and requires only one line to be called. It’ll come in handy when writing story-based games.
It is also annoying to write long function calls with the same parameters all the time. So let’s write a list with desired parameters to run the message display function with two arguments instead of five.
Now, let’s use the variable.
We managed to simplify this task to calling the function with ease and 1 short line of code!
Let’s not forget to make a while-loop so our window won’t close as soon as we launch the game.
Here’s the result of our hard work:
The progress might look insignificant, but later on we will use this function to write dialogue between characters, and much more!
PyGame Text
In this section we will look at how you include and manipulate text in Pygame. Text is valuable for many aspects of a good game. Text can be a little bit fiddly to set up in PyGame but once you have it set up it’s fairly easy to work with.
Getting Set Up
Before we begin, let’s create a new file (call it text.py) and copy in the template code from the previous section
Once you’ve saved your file with the template code in it, run the file to make sure you’ve copied it in ok. (You should get a blank white window.)
Including Text — The Simple Method
Including text in PyGame may be done as a three step process :
- Load the font for the text
- Render the text you want to a Text surface object
- Blit the text to the display surface (window)
Let’s start by adding a variable with a colour for our text (place it just below the existing BACKGROUND variable) :
- # Colours
- BACKGROUND = (255, 255, 255)
- TEXTCOLOUR = (200, 100, 0)
- # Game Setup
Next up we will add a few commands to render a basic text message in the center of the window :
- pygame.display.set_caption(‘My Game!’)
- # set up Fonts
- fontObj = pygame.font.Font(None, 32)
- textSufaceObj = fontObj.render(‘blah blah’, True, TEXTCOLOUR, None)
- # The main function that controls the game
What this does is :
- Create a font Object (fontObj) with the required font. (In this example we are just loading the PyGame default font by specifying it as ‘None’). We also specify the size of the font here as well (32)
- Create a surface object (textSurfaceObj) to hold the text we want to display. When we render we pass in four arguments :
- The text to render (‘blah blah’)
- If we are antialaising the text or not (True)
- The colour of the text (TEXTCOLOUR)
- The background colour of the surface (None — which means transparent)
Finally we will blit the surface to the window :
- WINDOW.fill(BACKGROUND)
- WINDOW.blit(textSufaceObj, (100, 100))
- pygame.display.update()
If you save and run the program now you should get a window with some text near the center.See if you can change the size, location and colour of the text.
Which fonts are available
The default font is a little bit boring. Thankfully it is very easy to change this. Your system will have a heap of built in fonts (any of which may be used). If you want to see what fonts are already available on your system, create a simple script as follows :
Installed-fonts.py
- import pygame, sys, random
- from pygame.locals import *
- pygame.init()
- fontsList = pygame.font.get_fonts()
- print (fontsList)
Any of the fonts in this list may then be utilised by replacing None (in the initial program) with the name of the font (within quotes) and changing Font to SysFont when loading the font. eg :
- pygame.display.set_caption(‘My Game!’)
- # set up Fonts
- # fontObj = pygame.font.Font(None, 32)
- fontObj = pygame.font.SysFont(‘courier’, 32)
- textSufaceObj = fontObj.render(‘blah blah’, True, TEXTCOLOUR, None)
- # The main function that controls the game
Loading your own fonts
The system fonts provide some variability in the look of the fonts but for a game we often want something a bit more exciting / suited to the style of our game interface. Fortunately it is very simple to find and use other fonts.
Any font in the .ttf (True Type Font) can be used. Let’s say we have a folder called fonts which is in the same location as our program. Including it is as simple as using the path to the font file :
- pygame.display.set_caption(‘My Game!’)
- # set up Fonts
- fontObj = pygame.font.Font(None, 32)
- fontObj = pygame.font.Font(‘fonts/Bullpen3D.ttf’, 32)
- textSufaceObj = fontObj.render(‘blah blah’, True, TEXTCOLOUR, None)
- # The main function that controls the game
If you find and download a font then update the program with the name of the font and run the program now you should get a window with some text near the center in your chosen font.There are many locations where you can obtain fonts to use in your games. Try doing a Google search for free fonts and you will find many websites to start from.
Including Text — Advanced Method
The simple method for including text works well enough but sometimes we need a bit more ability to manage placement of the text. We may achieve this by using a rect object to hold the text. Then we may use the features of the rect object to help with placement.
Text_Advanced.py
- import pygame, sys, random
- from pygame.locals import *
- pygame.init()
- # Colours
- BACKGROUND = (255, 255, 255)
- TEXTCOLOUR = (200, 100, 0)
- # Game Setup
- FPS = 60
- fpsClock = pygame.time.Clock()
- WINDOW_WIDTH = 400
- WINDOW_HEIGHT = 300
- WINDOW = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT))
- pygame.display.set_caption(‘My Game!’)
- # Set up fonts
- fontObj = pygame.font.Font(None, 32)
- textSufaceObj = fontObj.render(‘blah blah’, True, TEXTCOLOUR, None)
- textRectObj = textSufaceObj.get_rect()
- # The main function that controls the game
- def main () :
- looping = True
- # The main game loop
- while looping :
- # Get inputs
- for event in pygame.event.get() :
- if event.type == QUIT :
- pygame.quit()
- sys.exit()
- # Processing
- # This section will be built out later
- # Render elements of the game
- WINDOW.fill(BACKGROUND)
- WINDOW.blit(textSufaceObj, textRectObj)
- pygame.display.update()
- fpsClock.tick(FPS)
- main()
Line 21 — we create a rect object which will have the same dimensions as the text surface.
Line 41 — we blit the textSurfaceObj but use the textRectObj to get the coordinates for where to place it.
If you run the script you will notice that the text is placed in the top left corner of the window. That is because we haven’t moved the rect object from its default location yet.
The rect object isn’t the actual text but a rectangle which has the same dimensions as the text. We may now use the rectangle’s virtual attributes for location in order to more accurately place the text, or discover the width and height of the text. Here are the virtual attributes we can take advantage of :
- x, y
- top, left, bottom, right
- topleft, bottomleft, topright, bottomright
- midtop, midleft, midbottom, midright
- center, centerx, centery
- size, width, height
- w, h
Let’s say that part of the interface of our game is a line along the bottom of the screen, and we would like to place our text in the middle of that line, 15 pixels above it. This now becomes very easy.
- pygame.display.set_caption(‘My Game!’)
- BOTTOMLINEHEIGHT = 20
- # set up Fonts
- fontObj = pygame.font.Font(None, 32)
- textSufaceObj = fontObj.render(‘blah blah’, True, TEXTCOLOUR, None)
- textRectObj = textSufaceObj.get_rect()
- textRectObj.midbottom = (WINDOW_WIDTH // 2, WINDOW_HEIGHT — BOTTOMLINEHEIGHT — 15)
- # The main function that controls the game
- WINDOW.fill(BACKGROUND)
- WINDOW.blit(textSufaceObj, textRectObj)
- pygame.draw.line(WINDOW, TEXTCOLOUR, (0, WINDOW_HEIGHT — BOTTOMLINEHEIGHT), (WINDOW_WIDTH, WINDOW_HEIGHT — BOTTOMLINEHEIGHT), 3)
- pygame.display.update()
You could have achieved the same outcome using the simple method for rendering text and trial and error with the coordinates. This method will save you time and effort however, especially if you have several items you want to accurately place.A Simple Text Game
In this simple game we will print either Left or Right. The player has to press the opposite arrow key on the keyboard as fast as they can.
Simple_Text_Game.py
- import pygame, sys, random
- from pygame.locals import *
- pygame.init()
- # Colours
- BACKGROUND = (255, 255, 255)
- TEXTCOLOUR = (200, 100, 0)
- # Game Setup
- FPS = 60
- fpsClock = pygame.time.Clock()
- WINDOW_WIDTH = 400
- WINDOW_HEIGHT = 300
- WINDOW = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT))
- pygame.display.set_caption(‘My Game!’)
- # Set up fonts
- rightText = fontObj.render(‘Right’, True, TEXTCOLOUR, None)
- leftText = fontObj.render(‘Left’, True, TEXTCOLOUR, None)
- rightTextRectObj = rightText.get_rect()
- leftTextRectObj = leftText.get_rect()
- # Center the text on the window
- rightTextRectObj.center = (WINDOW_WIDTH // 2, WINDOW_HEIGHT //2)
- leftTextRectObj.center = (WINDOW_WIDTH // 2, WINDOW_HEIGHT //2)
- # Selects ramdomly either Left or Right
- def select_side () :
- side = »
- chosen = random.randint(0,1)
- if chosen == 1 :
- side = ‘Right’
- else :
- side = ‘Left’
- return side
- # The main function that controls the game
- def main () :
- looping = True
- target = select_side() # Prime the target before the main loop
- goes = 0 # How many goes the user has had
- score = 0
- rounds = 10 # How many rounds in the game
- active = True # Used so that the next target won’t be set until the user releases the key on the keyboard
- # The main game loop
- while looping :
- sideChosen = »
- # Get inputs
- for event in pygame.event.get() :
- if event.type == QUIT :
- pygame.quit()
- sys.exit()
- pressed = pygame.key.get_pressed()
- if pressed[K_RIGHT] :
- sideChosen = ‘Right’
- elif pressed[K_LEFT] :
- sideChosen = ‘Left’
- # Processing
- if sideChosen != » and sideChosen != target and active == True :
- print (‘Correct’)
- goes = goes + 1
- score = score + 1
- active = False
- elif sideChosen == target and active == True :
- print (‘Incorrect’)
- goes = goes + 1
- active = False
- elif active == False and sideChosen == » : # Enable the next round
- active = True
- target = select_side()
- if goes == rounds :
- looping = False
- # Render elements of the game
- WINDOW.fill(BACKGROUND)
- if target == ‘Right’ and active == True :
- WINDOW.blit(rightText, rightTextRectObj)
- elif target == ‘Left’ and active == True :
- WINDOW.blit(leftText, leftTextRectObj)
- pygame.display.update()
- fpsClock.tick(FPS)
- print (‘Game Over’)
- print (f’Your score was :
‘) - main()
There is a lot that could be improved with this game. It is intended simply to illustrate including text within your games. Check out the activities below for ideas on how you could improve it.
Activities
Even though our program doesn’t do too much just yet we can still tinker with a few elements to make sure we understand them.
Have a go at the following :
1. Can you improve your game so that it has up and down as well as left and right?
2. Can you make it to that the score is printed to the window as well? (instead of to the terminal)
3. Can you use shapes and other elements to create a more interesting interface for your game?
4. (extra challenging) The game in its current form doesn’t actually incorporate how fast the user was to select their answer. Can you improve the game so that the score is also based upon how quickly the user enters the answer?