I am trying to make a game and I am trying to render a lot of text. When the text renders, the rest of the text goes off the screen. Is there any easy way to make the text go to the next line of the pygame window?

helpT = sys_font.render \
                ("This game is a combination of all of the trends\n of 2016. When you press 'Start Game,' a menu will pop up. In order to beat the game, you must get a perfect score on every single one of these games.",0,(hecolor))
        screen.blit(helpT,(0, 0))
  • 2
    You'll have to calculate it yourself. Render each word and check how many words can fit the screen by using surface.get_width(). Then blit the rest on the another row which will be surface.get_height() pixels lower. – Ted Klein Bergman Feb 3 '17 at 0:52
  • PyGame doesn't render \n so you have to use render for every line separately. – furas Feb 3 '17 at 0:53
  • as @TedKleinBergman alreadu said - you can get surface height. You can also get next_line_rect = surface.get_rect() and then next_line_rect.top = prev_line_rect.bottom – furas Feb 3 '17 at 0:56

As I said in the comments; you have to render each word separately and calculate if the width of the text extends the width of the surface (or screen). Here's an example:

import pygame

SIZE = WIDTH, HEIGHT = (1024, 720)
FPS = 30
screen = pygame.display.set_mode(SIZE, pygame.RESIZABLE)
clock = pygame.time.Clock()

def blit_text(surface, text, pos, font, color=pygame.Color('black')):
    words = [word.split(' ') for word in text.splitlines()]  # 2D array where each row is a list of words.
    space = font.size(' ')[0]  # The width of a space.
    max_width, max_height = surface.get_size()
    x, y = pos
    for line in words:
        for word in line:
            word_surface = font.render(word, 0, color)
            word_width, word_height = word_surface.get_size()
            if x + word_width >= max_width:
                x = pos[0]  # Reset the x.
                y += word_height  # Start on new row.
            surface.blit(word_surface, (x, y))
            x += word_width + space
        x = pos[0]  # Reset the x.
        y += word_height  # Start on new row.

text = "This is a really long sentence with a couple of breaks.\nSometimes it will break even if there isn't a break " \
       "in the sentence, but that's because the text is too long to fit the screen.\nIt can look strange sometimes.\n" \
       "This function doesn't check if the text is too high to fit on the height of the surface though, so sometimes " \
       "text will disappear underneath the surface"
font = pygame.font.SysFont('Arial', 64)

while True:

    dt = clock.tick(FPS) / 1000

    for event in pygame.event.get():
        if event.type == pygame.QUIT:

    blit_text(screen, text, (20, 20), font)


enter image description here


There is no easy way to render text on multiple lines in pygame, but this helper function could provide some use to you. Just pass in your text (with newlines), x, y, and font size.

def render_multi_line(text, x, y, fsize)
        lines = text.splitlines()
        for i, l in enumerate(lines):
            screen.blit(sys_font.render(l, 0, hecolor), (x, y + fsize*i))

This is how I did it

amfolyt_beskrivelse_text = ['en amfolyt er et stof som både kan være en base, eller syre','så som']
    for x in amfolyt_beskrivelse_text:
        descriptioncounter += 1
        screen.blit((pygame.font.SysFont('constantia',12).render(x, True, BLACK)),(300,10*descriptioncounter))
    descriptioncounter = 0

but of course, I can only do that because my text starts a line distance from the top of the screen. If you start further down the screen you could do


One thing you could do is use a monospaced font. They have the same size for all characters and so are beloved by programmers. That's going to be my solution for handling the height/width problem.


You could use a .json file to load each line.

.json file (called first.json):

["Hello!", "How's it going?"]

And then load it into the file:

sys_font = pygame.font.SysFont(("Arial"),30)

def message_box(text):
    pos = 560 # depends on message box location
    pygame.draw.rect(root, (0,0,0), (100, 550, 800, 200)) #rectangle position varies
    for x in range(len(text)):
        rendered = sys_font.render(text[x], 0, (255,255,255))
        root.blit(rendered, ( 110, pos))
        pos += 30 # moves the following line down 30 pixels

with open('first.json') as text:

Don't forget to import json

Result: enter image description here

Hope this helps!


I recommend the ptext library which is able to recognize newline (\n) characters. You only need to call ptext.draw(text, position).

import pygame as pg
import ptext

screen = pg.display.set_mode((640, 480))
clock = pg.time.Clock()
BG_COLOR = pg.Color('gray12')
BLUE = pg.Color('dodgerblue')
# Triple quoted strings contain newline characters.
text = """Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua.

Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris
reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
culpa qui officia deserunt mollit anim id est laborum."""

done = False
while not done:
    for event in pg.event.get():
        if event.type == pg.QUIT:
            done = True

    ptext.draw(text, (10, 10), color=BLUE)  # Recognizes newline characters.


pygame multiline text

Your Answer

