1

I'm a bit confused. I have a class that inherits from the pygame.sprite.Sprite class. I want to add a border around the sprite when it shows on the screen, but the border does not appear

class Bird(pygame.sprite.Sprite):
    def __init__(self, filename, x, y):
        super().__init__()
        
        self.image = pygame.image.load('bird.png')
        self.rect = self.image.get_rect(topleft = (x, y))

    def draw(self, screen):
        pygame.draw.rect(screen, red, self.rect, 2)

When I call the sprite in the game loop, no border appears

bird_group.draw(screen)
bird_group.update()

I guess I'm doing something wrong but not sure what!

Ivan Yosifov
  • 59
  • 1
  • 6

1 Answers1

1

pygame.sprite.Group.draw does not call the draw method of the Sprite. [pygame.sprite.Group.draw() uses the image and rect attributes of the contained pygame.sprite.Sprites to draw the objects — you have to ensure that the pygame.sprite.Sprites have the required attributes. See pygame.sprite.Group.draw():

Draws the contained Sprites to the Surface argument. This uses the Sprite.image attribute for the source surface, and Sprite.rect. [...]

Therefore you must draw the rectangle on the image:

class Bird(pygame.sprite.Sprite):
    def __init__(self, filename, x, y):
        super().__init__()
        
        self.image = pygame.image.load('bird.png')
        self.rect = self.image.get_rect(topleft = (x, y))
        pygame.draw.rect(self.image, red, self.image.get_rect(), 2) # image.get_rect() not rect!

The border is drawn on self.image. It can't be removed. You have to use 2 images and switch the images:

class Bird(pygame.sprite.Sprite):
    def __init__(self, filename, x, y):
        super().__init__()
        
        self.image_no_border = pygame.image.load('bird.png')
        self.image_border = self.image.copy()
        pygame.draw.rect(self.image_border, red, self.image.get_rect(), 2) 

        self.border = True
        self.image = self.image_border if self.border else self.image_no_border
        self.rect = self.image.get_rect(topleft = (x, y))

    def click(self, pos):         
        if self.rect.collidepoint(pos):
            self.border = not self.border 
            self.image = self.image_border if self.border else self.image_no_border
Rabbid76
  • 202,892
  • 27
  • 131
  • 174
  • 1
    @IvanYosifov Sorry, copy/paste issue. It has to be `pygame.draw.rect(self.image, red, self.image.get_rect(), 2)` (`self.image` instead of `screen`) – Rabbid76 Oct 05 '21 at 19:34
  • 1
    Thank you. That solved the issue. Silly of me to pass the surface of the screen and not the surface of the sprite. Also self.image.get_rect() is different from self.rect. Must remember that. – Ivan Yosifov Oct 05 '21 at 19:54
  • 1
    @IvanYosifov From your code `self.rect = self.image.get_rect(topleft = (x, y))`. However `self.image.get_rect()` is `self.image.get_rect(topleft = (0, 0))` – Rabbid76 Oct 05 '21 at 19:57
  • would it be to much to ask how to remove the border on mouse click. `def update(self): if pygame.mouse.get_pressed()[0] and self.rect.collidepoint(pygame.mouse.get_pos()):` – Ivan Yosifov Oct 05 '21 at 20:08
  • @IvanYosifov `pygame.mouse.get_pressed()[0] ` is not an event it is `True` as long the button is hold down. Therefore the image will be changed continuously. See [Pygame mouse clicking detection](https://stackoverflow.com/questions/10990137/pygame-mouse-clicking-detection/64533684#64533684) – Rabbid76 Oct 05 '21 at 20:18