Search code examples
pythonpygamecollision-detectioncollision

Pygame Collision Not Working - pygame.sprite.collide_rect()


I'm working on a space shooter game and In that game, when an alien sprite collides with a player sprite, I want the game to end. When wrote the code for the collision, It didn't end the game. Can someone help me?

main.py

# IMPORTS
import pygame
from sprites import *
from config import *

# GAME
class Game():
    def __init__(self):
        # INIT PYGAME
        pygame.init()
        pygame.mixer.init()

        pygame.display.set_caption(TITLE)

        self.screen = pygame.display.set_mode((WIDTH, HEIGHT))
        self.clock = pygame.time.Clock()
        self.running = True

        self.player = Player()

    # NEW GAME
    def new(self):
        self.allSprites = pygame.sprite.Group()
        self.allAliens = pygame.sprite.Group()

        for amount in range(ALIEN_AMOUNT):
            self.alien = Alien()
            self.allAliens.add(self.alien)
            self.allSprites.add(self.alien)

        self.allSprites.add(self.player)

        self.run()

    # RUN GAME
    def run(self):
        self.playing = True

        while self.playing:
            self.clock.tick(FPS)

            self.events()
            self.update()
            self.draw()
            self.animate()
            self.collision()

    # DRAW
    def draw(self):
        self.screen.fill(BLACK)

        self.allAliens.draw(self.screen)
        self.allSprites.draw(self.screen)
        pygame.display.update()

    # ANIMATE
    def animate(self):
        pass

    # DETECT COLLISION
    def collision(self):
        # player collition with alien
        hits = pygame.sprite.collide_rect(self.alien, self.player)

        if hits:
            self.playing = False
            self.running = False

    # CHECK FOR EVENTS
    def events(self):
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                if self.playing:
                    self.playing = False

                self.running = False

    # UPDATE GAME
    def update(self):
        self.allSprites.update()

    # GAME OVER
    def gameOver(self):
        pass

    # START SCREEN
    def startScreen(self):
        pass

    # END SCREEN
    def endScreen(self):
        pass

game = Game()
game.startScreen()

while game.running:
    game.new()
    game.gameOver()

# QUIT
pygame.quit()
quit()

sprites.py

# IMPORTS
import pygame, random
from config import *

# PLAYER
class Player(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)

        self.image = pygame.image.load("assets/img/player.png").convert()
        self.image.set_colorkey(BLACK)
        self.rect = self.image.get_rect()
        self.rect.x = WIDTH / 2
        self.rect.y = HEIGHT - 50
        self.velX = 0

    def animate(self):
        self.rect.x += self.velX

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

        if keys[pygame.K_LEFT]:
            self.velX = -5
        elif keys[pygame.K_RIGHT]:
            self.velX = 5
        else:
            self.velX = 0

    def collision(self):
        # collision with walls
        if self.rect.left < 0:
            self.rect.left = 0
        elif self.rect.right > WIDTH:
            self.rect.right = WIDTH

    def update(self):
        self.animate()
        self.control()
        self.collision()

# ALIEN
class Alien(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)

        self.image = pygame.image.load("assets/img/rsz_alien.png").convert()
        self.image.set_colorkey(WHITE)
        self.rect = self.image.get_rect()
        self.rect.x = random.randrange(10, WIDTH - self.rect.w - 10)
        self.rect.y = random.randrange(-100, -10)
        self.velY = random.randrange(2, 8)

    def animate(self):
        self.rect.y += self.velY

    def collision(self):
        if self.rect.y > HEIGHT:
            self.reset()

    def update(self):
        self.animate()
        self.collision()

    def reset(self):
        self.rect.x = random.randrange(0, WIDTH)
        self.rect.y = random.randrange(-100, -10)
        self.velY = random.randrange(2, 8)

There's a config.py file but I don't think its needed for this question


Solution

  • You're only testing for collision with a single alien (which will be the last one that you created and assigned to self.alien). You need to iterate over all the aliens and test for collisions between the player and each of them.

    def collision(self):
        # player collision with each alien
        for alien in self.allAliens:
            hits = pygame.sprite.collide_rect(alien, self.player)
    
            if hits:
                self.playing = False
                self.running = False