Search code examples
pythonpygame

Need to blit transparency on a surface in Pygame


I was wanting to make a blind affect in my game using Pygame. I was thinking of making a surface, filling it with black, then removing a circle of color on the surface where the player is so you can see the player. I also wanted to do the same for a torch. I was wondering if i was able to erase parts of a surface in Pygame.


Solution

  • You can create a surface with an alpha channel (pass the pygame.SRCALPHA flag), fill it with an opaque color and then draw a shape with a transparent color onto it (alpha value 0).

    import pygame as pg
    
    
    pg.init()
    screen = pg.display.set_mode((800, 600))
    clock = pg.time.Clock()
    BLUE = pg.Color('dodgerblue4')
    # I just create the background surface in the following lines.
    background = pg.Surface(screen.get_size())
    background.fill((90, 120, 140))
    for y in range(0, 600, 20):
        for x in range(0, 800, 20):
            pg.draw.rect(background, BLUE, (x, y, 20, 20), 1)
    
    # This dark gray surface will be blitted above the background surface.
    surface = pg.Surface(screen.get_size(), pg.SRCALPHA)
    surface.fill(pg.Color('gray11'))
    
    done = False
    while not done:
        for event in pg.event.get():
            if event.type == pg.QUIT:
                done = True
            elif event.type == pg.MOUSEMOTION:
                surface.fill(pg.Color('gray11'))  # Clear the gray surface ...
                # ... and draw a transparent circle onto it to create a hole.
                pg.draw.circle(surface, (255, 255, 255, 0), event.pos, 90)
    
        screen.blit(background, (0, 0))
        screen.blit(surface, (0, 0))
    
        pg.display.flip()
        clock.tick(30)
    
    pg.quit()
    

    You can also achieve this effect with another surface instead of pygame.draw.circle. For example you could create a white image with some transparent parts in your graphics editor and pass BLEND_RGBA_MIN as the special_flags argument to Surface.blit when you blit it onto the gray surface.

    brush = pg.image.load('brush.png').convert_alpha()
    
    # Then in the while or event loop.
    surface.fill(pg.Color('gray11'))
    surface.blit(brush, event.pos, special_flags=pg.BLEND_RGBA_MIN)