Rendering text with multiple lines in pygame

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 will be similar to what others have posted, but I figured I'd upload my own code too:

    def box_text(surface, font, x_start, x_end, y_start, text, colour):
        x = x_start
        y = y_start
        words = text.split(' ')

        for word in words:
            word_t = font.render(word, True, colour)
            if word_t.get_width() + x <= x_end:
                surface.blit(word_t, (x, y))
                x += word_t.get_width() + 2
            else:
                y += word_t.get_height() + 4
                x = x_start
                surface.blit(word_t, (x, y))
                x += word_t.get_width() + 2

I think it's pretty self explanatory, you enter where you want your text to start (x_start) and where it should end, and then it pretty much goes down until your entered String is done.

An example of when I used in a personal project:

x_start = self.W / 2 - info_box.get_width() / 2 + 10

self.box_text(self.WINDOW, self.info_font, x_start, x_start + 430, self.H / 3 + 10, self.mage_text, self.white)

You would have to do some minor changes if you want the text to be justified though.


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
pygame.init()


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:
            quit()

    screen.fill(pygame.Color('white'))
    blit_text(screen, text, (20, 20), font)
    pygame.display.update()

Result

enter image description here