Salacc_I4
Salacc_I4

Reputation: 1

Why does .kill() leave sprites on screen instead of destroying?

I'm writing a code for sprites where once it leaves the screen, the .kill() command removes it. It instead just prints out the value and it still goes down. The parts I mention include run.play and the Note class' update where the code contains the .kill()

Code:

import pygame, sys, time, os

os.environ["SDL_VIDEO_CENTERED"] = "1"

win_width = 900
win_height = 700
fps = 60
white = (255, 255, 255)
black = (0, 0, 0)
grey = (80, 80, 80)
q_note = 98
w_note = 188
o_note = 278
p_note = 368


class Game:
    def __init__(self):
        self.clock = pygame.time.Clock()
        self.fps = 60
        self.init = pygame.init()
        self.caption = pygame.display.set_caption("BYOG")
        self.screen = pygame.display.set_mode((win_width, win_height), pygame.SRCALPHA)
        self.intro = True
        self.how_2_play = self.play = False


class Text:
    def __init__(self, size, text, color, xpos, ypos):
        self.font = pygame.font.SysFont("Roboto Mono", size)
        self.image = self.font.render(text, 1, color)
        self.rect = self.image.get_rect()
        self.rect = self.rect.move(xpos, ypos)


class Outline(pygame.sprite.Sprite):
    def __init__(self, x, y, x_pos, y_pos):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.Surface((x, y)).convert()
        self.image.fill(white)
        self.rect = self.image.get_rect()
        self.rect = pygame.Rect(x_pos, y_pos, x, y)


class Notes(pygame.sprite.Sprite):
    def __init__(self, x_pos, y_pos, side):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.image.load("images/q_rectangle.png").convert_alpha()
        self.image = pygame.transform.scale(self.image, (97, 55))
        self.rect = self.image.get_rect()
        self.rect = pygame.Rect(x_pos, y_pos, 90, 50)
        self.close = 0
        self.type = side

    def update(self, screen_group):
        self.rect.y += 6

        if 300 <= self.rect.y <= 460:
            self.close = 1
        if 461 <= self.rect.y <= 480:
            self.close = 2
        if 481 <= self.rect.y <= 500:
            self.close = 3
        if self.rect.y > 500:
            self.close = 4

        if self.rect.bottom > 0:
            screen_group.add(self)
        elif self.rect.top > win_height:
            self.kill()


def main():
    # Initial Variable
    run = Game()
    run.screen.fill(white)
    run.clock.tick(fps)
    pygame.display.flip()
    intro_music = pygame.mixer.Sound("Sounds/intro_song.ogg")
    game_music = pygame.mixer.Sound("Sounds/back_song.ogg")

    # Group
    note_group = pygame.sprite.Group()
    note_screen_group = pygame.sprite.Group()
    bracket_group = pygame.sprite.Group()

    # Objects
    boundary1 = Outline(2, 600, 100, 0)
    boundary2 = Outline(2, 600, 190, 0)
    boundary3 = Outline(2, 600, 280, 0)
    boundary4 = Outline(2, 600, 370, 0)
    boundary5 = Outline(2, 600, 460, 0)
    boundary6 = Outline(360, 2, 100, 450)
    boundary7 = Outline(360, 2, 100, 500)
    boundary8 = Outline(360, 2, 100, 600)

    n1 = Notes(q_note, -200, "q")
    n2 = Notes(w_note, -800, "w")
    n3 = Notes(o_note, -600, "o")
    n4 = Notes(p_note, -400, "p")

    intro_back = pygame.image.load("images/intro_back.jpg")
    intro_back = pygame.transform.scale(intro_back, (win_width, win_height))
    intro_rect = intro_back.get_rect()

    play_back = pygame.image.load("images/background_game.jpg")
    play_back = pygame.transform.scale(play_back, (win_width, win_height))
    play_rect = play_back.get_rect()

    intro_title = Text(150, "Osu!Mania", white, win_width / 5, win_height / 2 - 250)
    start_button = Text(75, "Start", white, win_width / 5 + 210, win_height / 2 + 175)
    start = run.screen.blit(start_button.image, start_button.rect)
    how_to_play = Text(75, "How to Play", white, win_width / 5 + 125, win_height / 2 + 250)
    question = run.screen.blit(how_to_play.image, how_to_play.rect)

    note_all_array = [n1, n2, n3, n4]
    bracket_group.add(boundary1, boundary2, boundary3, boundary4, boundary5, boundary6, boundary7, boundary8)

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_ESCAPE:
                pygame.quit()
                sys.exit()

    intro_music.play(-1)
    intro_music.set_volume(0.3)
    run.clock.tick(fps)
    pygame.display.flip()

    while run.intro:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()
            if event.type == pygame.MOUSEBUTTONUP:
                mouse = pygame.mouse.get_pos()
                if question.collidepoint(mouse):
                    run.intro = False
                    run.how_2_play = True
                elif start.collidepoint(mouse):
                    run.intro = False
                    run.play = True
                    intro_music.stop()
                    game_music.play(0)
                    game_music.set_volume(0.3)
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    pygame.quit()
                    sys.exit()

        run.screen.blit(intro_back, intro_rect)
        run.screen.blit(start_button.image, start_button.rect)
        run.screen.blit(intro_title.image, intro_title.rect)
        run.screen.blit(how_to_play.image, how_to_play.rect)

        run.clock.tick(fps)
        pygame.display.flip()

    while run.how_2_play:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    pygame.quit()
                    sys.exit()

        run.screen.fill(grey)
        run.clock.tick(fps)
        pygame.display.flip()

    while run.play:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()
            elif event.type == pygame.KEYDOWN:
                for n in note_screen_group:
                    if event.key == pygame.K_q:
                        if n.close == 1 and n.type == "q":
                            print("one")
                            n.kill()
                        elif n.close == 2 and n.type == "q":
                            print("two")
                            n.kill()
                        elif n.close == 3 and n.type == "q":
                            print("three")
                            n.kill()
                        elif n.close == 4 and n.type == "q":
                            print("four")
                            n.kill()
                    elif event.type == pygame.KEYDOWN and event.key == pygame.K_w:
                        if n.close == 1 and n.type == "w":
                            print("one")
                            n.kill()
                        elif n.close == 2 and n.type == "w":
                            print("two")
                            n.kill()
                        elif n.close == 3 and n.type == "w":
                            print("three")
                            n.kill()
                        elif n.close == 4 and n.type == "w":
                            print("four")
                            n.kill()
                    elif event.type == pygame.KEYDOWN and event.key == pygame.K_o:
                        if n.close == 1 and n.type == "o":
                            print("one")
                            n.kill()
                        elif n.close == 2 and n.type == "o":
                            print("two")
                            n.kill()
                        elif n.close == 3 and n.type == "o":
                            print("three")
                            n.kill()
                        elif n.close == 4 and n.type == "o":
                            print("four")
                            n.kill()
                    elif event.type == pygame.KEYDOWN and event.key == pygame.K_p:
                        if n.close == 1 and n.type == "p":
                            print("one")
                            n.kill()
                        elif n.close == 2 and n.type == "p":
                            print("two")
                            n.kill()
                        elif n.close == 3 and n.type == "p":
                            print("three")
                            n.kill()
                        elif n.close == 4 and n.type == "p":
                            print("four")
                            n.kill()

        run.screen.blit(play_back, play_rect)

        for n in note_all_array:
            n.update(note_screen_group)

        note_screen_group.draw(run.screen)

        bracket_group.draw(run.screen)
        run.clock.tick(fps)
        pygame.display.flip()


if __name__ == "__main__":
    while True:
        main()

Any help is appreciated, am running pygame 1.9.6 on python 3. Thanks!

Upvotes: 0

Views: 736

Answers (2)

Ted Klein Bergman
Ted Klein Bergman

Reputation: 9766

You're adding the sprites back into the group every frame (in the Notes .update() method). So when you call .kill() (which removes the sprite from the group), you add it back in immediately afterwards.

# Up here you kill the note.

for n in note_all_array:
    n.update(note_screen_group)  # Here you add the note back.

note_screen_group.draw(run.screen)  # Here you draw the note

Upvotes: 0

Glenn Mackintosh
Glenn Mackintosh

Reputation: 2779

Nothing is drawn on the screen that you do not draw.

If you want to remove an image from the screen you have to draw something in its place. Usually you redraw part of the background.

When you kill() a sprite, it gets removed from all the sprite groups and so stops getting called but that is all the happens. There is no other action that occurs as a result of kill() - like somehow removing its image from the display surface. Unless the entire screen is redrawn (by a background fill or something), the kill()ed sprites image will stay on the screen until something draws over it. If you do not redraw the background each frame, you need to redraw the part of the background the sprite used to cover, or draw something else there to cover the old sprites image.

Upvotes: 2

Related Questions