'Pygame Rendering Text 1 by 1 Causes Lag In Game How Do I Fix This?

when ever I try to display to render this text 1 by 1 it seems to slow my game down and make everything run slow and for some reason it starts the text as well I want it to end when its finished typing the text VIDEO< as you can see in the video the text keeps playing the game keeps lagging for some reason when ever each of the text is rendered on the screen


    def show_text(string):
        WHITE = (255, 255, 255)
        text = ''
        font = pygame.font.Font("Alice.ttf", 30)
        for i in range(len(string)):
            text += string[i]
            text_surface = font.render(text, True, WHITE)
            text_rect = text_surface.get_rect()
            text_rect.center = (700/2, 800/2)
            window.blit(text_surface, text_rect)
            pygame.display.update()
            pygame.time.wait(100)

        display_text_animation('Hello World!')

heres the full code there all rects execept the Alice.tff < text style

import pygame, sys
from pygame.locals import *

WINDOW_WIDTH = 500
WINDOW_HEIGHT = 500

pygame.init()
DISPLAYSURF = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT))

BLACK = (  0,   0,   0)
WHITE = (255, 255, 255)


class player:
    def __init__(self,x,y,height,width,color):
        self.x = x
        self.y = y
        self.height = height
        self.width = width
        self.color = color
        self.rect = pygame.Rect(x,y,height,width)
    def draw(self):
        self.rect.topleft = (self.x,self.y)
        pygame.draw.rect(DISPLAYSURF,self.color,self.rect)

white = (120,120,120)
player1 = player(150,150,50,50,white)
def display_text_animation(string):
    text = ''
    for i in range(len(string)):
        text += string[i]
        font = pygame.font.Font("Alice.ttf", 30)
        text_surface = font.render(text, True, white)
        text_rect = text_surface.get_rect()
        DISPLAYSURF.blit(text_surface, text_rect)
        pygame.display.update()
        pygame.time.wait(100)

def main():
    while True:
        for event in pygame.event.get():
            if event.type == QUIT:
                pygame.quit()
                sys.exit()
        keys = pygame.key.get_pressed()
        if keys[pygame.K_d]:
            player1.x += 5
        if keys[pygame.K_a]:
            player1.x -= 5
        DISPLAYSURF.fill((0,0,0))        
        player1.draw()
        display_text_animation('Hello World!')
main()


Solution 1:[1]

Do not create the pygame.font.Font object in every frame. Creating a font object is very time consuming. Every time the Font object is created, the font file ("Alice.ttf") must be read and interpreted. Create the Fontobject before the application loop during initialization.

Furthermore do not animate the text in a loop use the application loop. Use pygame.time.get_ticks() to measure the time. Calculate the number of letters to be displayed as a function of time:

font = pygame.font.Font("Alice.ttf", 30)
def display_text_animation(string, start_time):
    current_time = pygame.time.get_ticks()  
    letters = (current_time - start_time) // 100 
    text = string[:letters]
    WHITE = (255, 255, 255)
    text_surface = font.render(text, True, WHITE)
    text_rect = text_surface.get_rect()
    text_rect.center = (700/2, 800/2)
    DISPLAYSURF.blit(text_surface, text_rect)
def main():
    text = 'Hello World!'
    start_time = pygame.time.get_ticks()    

    clock = pygame.time.Clock()
    while True:
        clock.tick(60)
        for event in pygame.event.get():
            if event.type == QUIT:
                pygame.quit()
                sys.exit()
        keys = pygame.key.get_pressed()
        if keys[pygame.K_d]:
            player1.x += 5
        if keys[pygame.K_a]:
            player1.x -= 5

        DISPLAYSURF.fill((0,0,0))        
        player1.draw()
        display_text_animation(text, start_time)
        pygame.display.update()

When ever you want to animate a new text you just have to set text and start_time. e.g:

text = "New text"
start_time = pygame.time.get_ticks() 

Minimal typewriter effect example:

import pygame

pygame.init()
window = pygame.display.set_mode((500, 150))
clock = pygame.time.Clock()
font = pygame.font.SysFont(None, 100)

background = pygame.Surface(window.get_size())
ts, w, h, c1, c2 = 50, *window.get_size(), (32, 32, 32), (64, 64, 64)
tiles = [((x*ts, y*ts, ts, ts), c1 if (x+y) % 2 == 0 else c2) for x in range((w+ts-1)//ts) for y in range((h+ts-1)//ts)]
for rect, color in tiles:
    pygame.draw.rect(background, color, rect)

text = 'Hello World'
text_len = 0
typewriter_event = pygame.USEREVENT+1
pygame.time.set_timer(typewriter_event, 100)
text_surf = None

run = True
while run:
    clock.tick(60)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False
        if event.type == typewriter_event:
            text_len += 1
            if text_len > len(text):
                text_len = 0
            text_surf = None if text_len == 0 else font.render(text[:text_len], True, (255, 255, 128))

    window.blit(background, (0, 0))
    if text_surf:
        window.blit(text_surf, text_surf.get_rect(midleft = window.get_rect().midleft).move(40, 0))
    pygame.display.flip()

pygame.quit()
exit()

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1