pythonpygamepygame-surface

Unable to undraw on a transparent surface in pygame


I'm attempting to create a method to essentially erase a drawing on a surface. I have the functionality working for an surface that contains a png, but when I use the same method to remove a surface that is drawn on by pygame.draw.lines() it is not erasing.

The major difference between the two surfaces is one is transparent and other is not. I think I may not understand fully how pygames transparent surfaces work.

Not working undraw():

class MovementComponent(AbstactComponent):
    def __init__(self) -> None:
        super().__init__()
        game_surfaces = GameSurfaces() #singleton class that rerenders all of the surfaces in order
        self.movement_surface = game_surfaces.movement_surface
        self.path_surface = pg.Surface(self.movement_surface.get_size(), pg.SRCALPHA)
        self.path_surface.set_alpha(150)

    def draw_movement(self):
        if len(self.queue()) >= 2:
            tile_centers = []
            for tile in self.queue():
                tile_centers.append(tile.center_pixel)

            pg.draw.lines(
                self.path_surface, 
                self.character.color, 
                False, tile_centers, 3
            )
            
            self.movement_surface.blit(self.path_surface, (0,0))

    def undraw_movement(self):
        empty = pg.Color(0,0,0,0)
        self.path_surface.fill(empty)
        self.movement_surface.blit(self.path_surface, (0,0))

The working undraw in another component:

class SpriteComponent(AbstactComponent):
    NORMAL_SIZE = (55,55)

    def __init__(self, image: pg.image):
        surfaces = GameSurfaces()
        self.char_surface = surfaces.character_surface
        self.pixel_pos: (int,int) = None

        self.standard_image = pg.transform.scale(image, self.NORMAL_SIZE)
        self.empty = pg.Color(0,0,0,0)

    def draw(self, pixel_pos: (int, int)):
        self.pixel_pos = pixel_pos
        top_left_pixel = self.get_topleft_pos(pixel_pos)
        self.char_surface.blit(self.standard_image, top_left_pixel)

    def undraw(self, pixel_pos: (int, int)=None):
        pixel_pos = pixel_pos if pixel_pos else self.pixel_pos
        top_left_pixel = self.get_topleft_pos(self.pixel_pos)
        rect_to_clear = pg.Rect(top_left_pixel, self.NORMAL_SIZE)
        self.char_surface.fill(self.empty, rect_to_clear)

Solution

  • A transparent Surface is blended with the background. When deleting, however, you want to cover the background completely. Therefore you have to make the Surface temporarily opaque again for the deletion. If you call set_alpha with the argument None, the previously set transparency is canceled again:

    class MovementComponent(AbstactComponent):
        # [...]
    
        def undraw_movement(self):
            empty = pg.Color(0,0,0,0)
            self.path_surface.fill(empty)
            self.path_surface.set_alpha(None)
            self.movement_surface.blit(self.path_surface, (0,0))
            self.path_surface.set_alpha(150)