How to clean up sprites without covering other things?

Question:

I’m trying to make tetris in pygame and I’ve got collisions and movement down but, when a mask collides with a placed block, the rect I use to cover the old sprite covers parts of the placed sprite:

def replace(self):
    pygame.draw.rect(board_surface,(0,0,0),(self.rect.topleft, self.rect.size))

This code is in my sprite class:

class Block(pygame.sprite.Sprite):
    def __init__(self, blocks):
        super().__init__()

        self.random_block = randint(1,7)

        self.image = blocks[self.random_block]
        self.image = pygame.transform.scale(self.image,(self.image.get_width()*.4, self.image.get_height()*.4))
        self.rect = self.image.get_rect()
        self.rect.topleft = (300,0)
        self.mask = pygame.mask.from_surface(self.image)

    def replace(self):
        pygame.draw.rect(board_surface,(0,0,0),(self.rect.topleft, self.rect.size))



    def handle_keys(self, board_s, block, unactive_blocks):
        keys = pygame.key.get_pressed()
        if keys[pygame.K_LEFT] or keys[pygame.K_a]:
            if self.rect.left - 60 >= 0:
                self.replace(block_colours)
                self.rect.x -= 60
                self.draw(block_group, board_s)
        elif keys[pygame.K_RIGHT] or keys[pygame.K_d]:
            if self.rect.right + 60 <= 600:
                self.replace(block_colours)
                self.rect.x += 60
                self.draw(block_group, board_s)
        elif keys[pygame.K_UP] or keys[pygame.K_w]:
            self.replace(block_colours)
            topleft = self.rect.topleft
            self.image = pygame.transform.rotate(self.image, 90)
            self.rect = self.image.get_rect()
            self.rect.topleft = topleft
            self.mask = pygame.mask.from_surface(self.image)
            self.draw(block_group, board_s)
        elif keys[pygame.K_DOWN] or keys[pygame.K_s]:
            if self.rect.bottom + 60 <= 1200:
                self.replace(block_colours)
                self.rect.y += 60
                if pygame.sprite.spritecollide(block,unactive_blocks,False,pygame.sprite.collide_mask):
                    self.rect.y -= 60
                    block_sprite(blocks, block)
                self.draw(block_group, board_s)
            else:
                block_sprite(blocks, block)
    
    def move_every_second(self, block, unactive_blocks):
        if self.rect.bottom + 60 <= 1200:
            self.replace(block_colours)
            self.rect.y += 60
            if pygame.sprite.spritecollide(block,unactive_blocks,False,pygame.sprite.collide_mask):
                self.rect.y -= 60
                block_sprite(blocks, block)
            self.draw(block_group, board_s)
        else:
            block_sprite(blocks, block)
    
    def draw(self, block_group, board_s):
        print(self.rect.x,self.rect.y)
        block_group.draw(board_s)

Full code at pastebin.com/59E74zBJ

Asked By: shoewis

||

Answers:

The usual and simplest method is to redraw the scene in each frame. What if the background does not have a uniform color? How are you going to restore the background if it is an image?

However, you can create a Surface from a Mask with to_surface and blit this Surface instead of drawing a rectangle:

cover_image = self.mask.to_surface(setcolor=(0, 0, 0, 255), unsetcolor=(0, 0, 0, 0))
board_surface.blit(cover_image, self.rect.topleft)
Answered By: Rabbid76
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.