1

Here is my code:

hit_list = pygame.sprite.groupcollide(all_bats, all_sword, False, True, collided = pygame.sprite.collide_mask(bat_front1, sword1))
for self in hit_list:
    self.bat_health -= 1 
    if self.bat_health == 0:
        self.kill()

bat_front is the image I am using for the enemies in all_bats, and sword1 is the image I am using for the enemies in all_sword. This code is in the update section of my bat class. When I run the code I get the error message 'pygame.Surface' object has no attribute 'rect' and the line xoffset = right.rect[0] - left.rect[0] is highlighted from sprite.py. I get no error when I don't use a collided function but the hit collision is pretty bad. I have no clue why I get the error message :/

Owen Penn
  • 163
  • 9

2 Answers2

1

If you have defined the mask correctly, the sprite class will automatically use the mask for collisions. It is not necessary to call it as per the question - you might only do this to collide self-drawn polygons or suchlike.

If the image passed as bat_image has transparency, this is probably all happening correctly already.

class Bat(pygame.sprite.Sprite):
    def __init__( self, bat_x, bat_y, bat_image ):
        pygame.sprite.Sprite.__init__(self)
        self.image = bat_image
        self.mask  = pygame.mask.from_surface(self.image)
        self.rect  = self.image.get_rect()
        self.rect.topleft = (bat_x, bat_y)
        self.health = 10

    def handleCollision( self, with_swords  ):
        # TODO
        print( "Bat.handleCollision()" )
        self.health -= 1
        if ( self.health <= 0 ):
            self.kill()

It's more efficient to move the groupcollide outside of your sprite update(), since it needs only be performed once for all sprites.

# main loop
while not exiting:

    # handle events
    [...]

    # check collisions for all bats
    hit_list = pygame.sprite.groupcollide( all_bats, all_sword, False, False )
    for bat in hit_list.keys():
        bat.handleCollision( hit_list[ bat ] )  

    # paint the screen
    # etc.
Kingsley
  • 14,398
  • 5
  • 31
  • 53
1

You should pass the function itself as collided argument; not the result of calling it.

So instead of

hit_list = pygame.sprite.groupcollide(all_bats, all_sword, False, True, collided = pygame.sprite.collide_mask(bat_front1, sword1))

you should use

hit_list = pygame.sprite.groupcollide(all_bats, all_sword, False, True, collided = pygame.sprite.collide_mask)

The groupcollide will then use the collide_mask to check for collisions by calling it with the sprites in all_bats and all_sword.

sloth
  • 99,095
  • 21
  • 171
  • 219