Pygame doesn't kill

Question:

If player and enemy collide, I want the program to detect a collision between player and enemy(almost bottom of code). If this happens, its supposed to run the "killBullet()" function. It actually runs it, but "self.kill()" doesnt work. It really drives me nuts, since appearently it works on "update".

import pygame
import random
from pygame.locals import (
    RLEACCEL,
    K_UP,
    K_DOWN,
    K_LEFT,
    K_RIGHT,
    K_ESCAPE,
    KEYDOWN,
    QUIT,
)

pygame.mixer.init()
pygame.font.init()
pygame.init()

SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600

global lives
lives = 3

class Player(pygame.sprite.Sprite):
    def __init__(self):
        super(Player, self).__init__()
        self.surf = pygame.image.load("jet.png").convert()
        self.surf.set_colorkey((255, 255, 255), RLEACCEL)
        self.rect = self.surf.get_rect()

    def update(self, pressed_keys):
        if pressed_keys[K_UP]:
            self.rect.move_ip(0, -5)
            move_up_sound.play()
        if pressed_keys[K_DOWN]:
            self.rect.move_ip(0, 5)
            move_down_sound.play()
        if pressed_keys[K_LEFT]:
            self.rect.move_ip(-5, 0)
        if pressed_keys[K_RIGHT]:
            self.rect.move_ip(5, 0)

        #Keep on screen
        if self.rect.left < 0:
            self.rect.left = 0
        if self.rect.right > SCREEN_WIDTH:
            self.rect.right = SCREEN_WIDTH
        if self.rect.top <= 0:
            self.rect.top = 0
        if self.rect.bottom >= SCREEN_HEIGHT:
            self.rect.bottom = SCREEN_HEIGHT

class Enemy(pygame.sprite.Sprite):
    def __init__(self):
        super(Enemy, self).__init__()
        self.surf = pygame.image.load("missile.png").convert()
        self.surf.set_colorkey((255, 255, 255), RLEACCEL)
        self.rect = self.surf.get_rect(
            center=(
                random.randint(SCREEN_WIDTH + 20, SCREEN_WIDTH + 100),
                random.randint(0, SCREEN_HEIGHT),
            )
        )
        self.speed = random.randint(5, 20)

    def killBullet(self):
        self.kill()
        #global lives

    def update(self):
        self.rect.move_ip(-self.speed, 0)
        if self.rect.right < 0:
            self.kill()

class Cloud(pygame.sprite.Sprite):
    def __init__(self):
        super(Cloud, self).__init__()
        self.surf = pygame.image.load("cloud.png").convert()
        self.surf.set_colorkey((0, 0, 0), RLEACCEL)
        self.rect = self.surf.get_rect(
            center=(
                random.randint(SCREEN_WIDTH + 20, SCREEN_WIDTH + 100),
                random.randint(0, SCREEN_HEIGHT),
            )
        )

    def update(self):
        self.rect.move_ip(-5, 0)
        if self.rect.right < 0:
            self.kill()

screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))

ADDENEMY = pygame.USEREVENT + 1
pygame.time.set_timer(ADDENEMY, 250)
ADDCLOUD = pygame.USEREVENT + 2
pygame.time.set_timer(ADDCLOUD, 1000)

player = Player()

enemies = pygame.sprite.Group()
cloud = pygame.sprite.Group()
all_sprites = pygame.sprite.Group()
all_sprites.add(player)

font = pygame.font.SysFont(None, 30)
clock = pygame.time.Clock()
timer = 0

pygame.mixer.music.load("Apoxode_-_Electric_1.mp3")
pygame.mixer.music.play(loops=-1)
move_up_sound = pygame.mixer.Sound("Rising_putter.ogg")
move_down_sound = pygame.mixer.Sound("Falling_putter.ogg")
collision_sound = pygame.mixer.Sound("Collision.ogg")

running = True
while running:
    for event in pygame.event.get():
        if event.type == KEYDOWN:
            if event.key == K_ESCAPE:
                running = False
        elif event.type == QUIT:
            running = False
        elif event.type == ADDENEMY:
            new_enemy = Enemy()
            enemies.add(new_enemy)
            all_sprites.add(new_enemy)
        elif event.type == ADDCLOUD:
            new_cloud = Cloud()
            cloud.add(new_cloud)
            all_sprites.add(new_cloud)

    pressed_keys = pygame.key.get_pressed()
    player.update(pressed_keys)

    enemies.update()
    cloud.update()


    # Fill the screen with blue
    screen.fill((135, 206, 250))

    text = font.render(str(timer), True, (255,255,255))
    screen.blit(text, (0,(SCREEN_HEIGHT-text.get_rect().height)))
    timer=timer+1

    for entity in all_sprites:
        screen.blit(entity.surf, entity.rect)

    if pygame.sprite.spritecollideany(player, enemies):
        Enemy().killBullet()
        lives -= 1
        print(lives)
        if lives <= 0:
            player.kill()
            move_up_sound.stop()
            move_down_sound.stop()
            collision_sound.play()
            running = False
            
    pygame.display.update()
    clock.tick(30)

pygame.mixer.music.stop()
pygame.mixer.quit()
Asked By: DickwadTheGreat

||

Answers:

pygame.sprite.spritecollideany tests whether a sprite intersects anything in a group and returns the first sprite detected or None. You have to kill the detected Sprite instead of a new enemy instance:

while running:
    # [...]

    enemy = pygame.sprite.spritecollideany(player, enemies)
    if enemy:  
        enemy.killBullet()
        lives -= 1
        
        # [...]
Answered By: Rabbid76

I tried running the game and noticed that the one collision continues to reduce the number of lives automatically. I saw you commented out the global lives in the killBullet method and moved the lives -= operator back up there.

def killBullet(self):
    self.kill()
    global lives
    lives -= 1

That way the missile disappears, and the game keeps going. I guess you could replace the jet asset with a little explosion image and then display an interim screen with the number of lives decreasing.

Answered By: Victor Yamaykin
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.