简体   繁体   中英

Pygame sprite-collision detection doesnt work

When I trie to detect a collision between the two rectangles with hit = pygame.sprite.groupcollide(enemy_sprites, player_sprites, 1, 1) it only prints "HIT" once when I start the program

also I tried to detect the collision with hit = pygame.sprite.spritecollide(player_sprites, enemy_sprites, 1) but there was this error:

Traceback (most recent call last):
File "D:/Python/PyCharm/test/src/Main/test.py", line 104, in
hit = pygame.sprite.spritecollide(player_sprites, enemy_sprites, 1)
File "D:\\Programme\\python\\lib\\site-packages\\pygame\\sprite.py", line 1523, in spritecollide ''''spritecollide = sprite.rect.colliderect AttributeError: 'Group' object has no attribute 'rect'

    import pygame


class Player(pygame.sprite.Sprite):

    def __init__(self, x, y, width, height):
        pygame.sprite.Sprite.__init__(self)

        # def colours
        self.GREEN = (0, 255, 255)
        self.BLACK = (0, 0, 0)

        self.playerx = x
        self.playery = y
        self.playerW = width
        self.playerH = height
        self.vel = 5

        self.player_image = pygame.Surface((self.playerW, self.playerH))
        self.player_image.fill(self.GREEN)
        self.rect = self.player_image.get_rect()

    def handleKeys(self):
        keys = pygame.key.get_pressed()

        if keys[pygame.K_UP]:
            if self.playery >= self.vel:
                self.playery -= self.vel
        elif keys[pygame.K_DOWN]:
            if self.playery + 50 <= screenH - self.vel:
                self.playery += self.vel
        elif keys[pygame.K_LEFT]:
            if self.playerx >= self.vel:
                self.playerx -= self.vel
        elif keys[pygame.K_RIGHT]:
            if self.playerx + 50 <= screenW - self.vel:
                self.playerx += self.vel
        else:
            pass

    def drawPlayer(self, surface):
        player_sprites.update()

        surface.fill(self.BLACK)

        surface.blit(self.player_image, (self.playerx, self.playery))


class Enemy(pygame.sprite.Sprite):
    def __init__(self, x, y, width, height):
        pygame.sprite.Sprite.__init__(self)

        self.enemyX = x
        self.enemyY = y
        self.enemyW = width
        self.enemyH = height

        self.RED = (255, 0, 0)

        self.enemy_image = pygame.Surface((self.enemyW, self.enemyH))
        self.enemy_image.fill(self.RED)
        self.rect = self.enemy_image.get_rect()

    def drawEnemy(self, surface):
        enemy_sprites.update()

        surface.blit(self.enemy_image, (self.enemyX, self.enemyY))


# def some variables
pygame.init()

clock = pygame.time.Clock()

screenW = 500
screenH = 500
playerx = 200
playery = 200

wn = pygame.display.set_mode((screenW, screenH))
pygame.display.set_caption("Test program")

# player
player_sprites = pygame.sprite.Group()
player = Player(100, 100, 50, 50)
player_sprites.add(player)

# enemy
enemy_sprites = pygame.sprite.Group()
enemy = Enemy(200, 200, 50, 50)
enemy_sprites.add(enemy)

# main loop
run = True
while run:

    clock.tick(60)

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False

    hit = pygame.sprite.groupcollide(enemy_sprites, player_sprites, 1, 1)

    if hit:
        print("HIT")
        hit = False

    player.handleKeys()
    player.drawPlayer(wn)
    enemy.drawEnemy(wn)

    pygame.display.flip()

pygame.quit()

pygame.sprite.groupcollide compares the .rect properties in the pygame.sprite.Sprite objects in the group.

Further note, that if the the 2nd and 3rd parameter of pygame.sprite.groupcollide() are not False , then the sprites are "killed" and removed from the groups in case of a collision.
You can avoid this by passing False :

hit = pygame.sprite.groupcollide(enemy_sprites, player_sprites, False, False)

You've to update the .rect properties when the position is initialized or changed:

class Player(pygame.sprite.Sprite):

    def __init__(self, x, y, width, height):
        pygame.sprite.Sprite.__init__(self)

        # [...]

        self.player_image = pygame.Surface((self.playerW, self.playerH))
        self.player_image.fill(self.GREEN)
        self.rect = self.player_image.get_rect()

        self.rect.topleft = (self.playerx, self.playery)  # <--- init .rect.topleft

    def handleKeys(self):
        keys = pygame.key.get_pressed()

        if keys[pygame.K_UP]:
        # [...]        

        self.rect.topleft = (self.playerx, self.playery) # <---- update .rect.topleft
class Enemy(pygame.sprite.Sprite):
    def __init__(self, x, y, width, height):
        pygame.sprite.Sprite.__init__(self)

        # [...]

        self.enemy_image = pygame.Surface((self.enemyW, self.enemyH))
        self.enemy_image.fill(self.RED)
        self.rect = self.enemy_image.get_rect()

        self.rect.topleft = (self.enemyX, self.enemyY)   # <--- init .rect.topleft

Alternatively you can remove self.playerx , self.playery , self.enemyX and self.enemyY use self.rect.x respectively seld.rect.y instead. See pygame.Rect .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM