How to render transparent text with alpha channel in PyGame?

Viewed 6696

I am using pygame.font.Font.render() to render some text. I'd like the text to be translucent, ie have an alpha value other than 255, so I tried passing a color argument with an alpha value (eg (255, 0, 0, 150)) as the color argument for pygame.font.Font.render() but it didn't have any effect. I also tried using pygame.Surface.convert_alpha() on the resulting Surface object, but that didn't do anything either. Any ideas?

3 Answers

When using the pygame.font module, the alpha channel of the text color is not taken into account when rendering a text, but see pygame.font.Font.render:

Antialiased images are rendered to 24-bit RGB images. If the background is transparent a pixel alpha will be included.

and pygame.Surface.set_alpha

Changed in pygame 2.0: per-surface alpha can be combined with per-pixel alpha.

Hence it is completely sufficient to set the transparency after rendering the text with set_alpha. This even works for anti-aliased text:

font = pygame.font.SysFont(None, 150)

text_surf = font.render('test text', True, (255, 0, 0))
text_surf.set_alpha(127)

window.blit(text_surf, (x, y))

Minimal example: repl.it/@Rabbid76/PyGame-TransparentText

import pygame

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

text_surf = font.render('test text', True, (255, 0, 0))
text_surf.set_alpha(127)

background = pygame.Surface(window.get_size())
ts, w, h, c1, c2 = 50, *window.get_size(), (128, 128, 128), (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)

run = True
while run:
    clock.tick(60)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False

    window.blit(background, (0, 0))
    window.blit(text_surf, text_surf.get_rect(center = window.get_rect().center))
    pygame.display.flip()

pygame.quit()
exit()

By using the pygame.freetype module, you can use a transparent color directly when creating a text surface:

ft_font = pygame.freetype.SysFont('Times New Roman', 150)

text_surf2, text_rect2 = ft_font.render('test text', (255, 0, 0, 128))
window.blit(text_surf2, (x, y))

Or if you are rendering the text directly onto a surface:

ft_font = pygame.freetype.SysFont('Times New Roman', 150)

ft_font.render_to(window, (x, y), 'test text', (255, 0, 0, 128))

Minimal example: repl.it/@Rabbid76/PyGame-TransparentFreeTypeText

import pygame
import pygame.freetype

pygame.init()

window = pygame.display.set_mode((500, 300))
clock = pygame.time.Clock()
ft_font = pygame.freetype.SysFont('Times New Roman', 150)

text_surf2, text_rect2 = ft_font.render('test text', (255, 0, 0, 128))

background = pygame.Surface(window.get_size())
ts, w, h, c1, c2 = 50, *window.get_size(), (128, 128, 128), (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)

run = True
while run:
    clock.tick(60)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False

    window.blit(background, (0, 0))
    
    text_rect = ft_font.get_rect('test text')
    text_rect.center = (window.get_width() // 2, window.get_height() // 2 - 70)
    ft_font.render_to(window, text_rect.topleft, 'test text', (255, 0, 0, 128))
    
    text_rect2.center = (window.get_width() // 2, window.get_height() // 2 + 70)
    window.blit(text_surf2, text_rect2)
    
    pygame.display.flip()

pygame.quit()
exit()

See also Text and font

You can change the transparency of the entire surface using a individual alpha value. Use surf=pygame.Surface((size,pygame.SRCALPHA). Now if you change the alpha value by setting surf.set_alpha(alpha) of the screen, the surface around the text wont be black anymore.

Related