Pixeled
Pixeled

Reputation: 322

Why won't the remove command work for my Pygame sprite list?

I am making a game in Pygame where the sprite just goes to the end of the screen then teleports back, and obstacles 1-2 obstacles spawn. When 1 obstacle spawns the other one is still there but invisible and ends the game. Even though I killed it and removed it from the sprite list. What is wrong with my code?

import pygame
import random
import time

jump_v = 7     
isjump = False
v = 5
m = 1
o = 2

GRAY = (192, 192, 192)
RED  = (255,   0,   0)
BLACK = (0 ,    0,   0)
class Player(pygame.sprite.Sprite):
    
    def __init__(self, color, x, y, width, weight):
        super().__init__()
        self.color = color
        self.image = pygame.Surface([width, weight])
        self.image.fill(color)
        self.rect = self.image.get_rect()
        self.rect.x = x
        self.rect.y = y

    def update(self):
        global o
        self.rect.x += 7

        if self.rect.colliderect(obstacle1.rect):
            self.rect.x = 0
            o = random.randint(0,2)
            if o == 1:
                obstacle1.rect.x = (random.randint(300, 900))
                obstacle2.kill()
                all_sprites_list.remove(obstacle2)
            if o == 2:
                obstacle1.rect.x = (random.randint(300, 900))
                obstacle2.rect.x = (random.randint(300, 900))
                if obstacle2.rect.x - obstacle1.rect.x > 0:
                    while obstacle1.rect.x - obstacle2 .rect.x < 100:
                        obstacle1.rect.x = (random.randint(300, 900))
                        obstacle2.rect.x = (random.randint(300, 900))
        if self.rect.colliderect(obstacle2.rect):
            self.rect.x = 0
            o = random.randint(0,2)
            if o == 1:
                obstacle1.rect.x = (random.randint(300, 900))
                obstacle2.kill()
                all_sprites_list.remove(obstacle2)
            if o == 2:
                obstacle1.rect.x = (random.randint(300, 900))
                obstacle2.rect.x = (random.randint(300, 900))
                if obstacle2.rect.x - obstacle1.rect.x > 0:
                    while obstacle1.rect.x - obstacle2 .rect.x < 100:
                        obstacle1.rect.x = (random.randint(300, 900))
                        obstacle2.rect.x = (random.randint(300, 900))
        if self.rect.x >= 950:
            self.rect.x = 0
            o = random.randint(0,2)
            if o == 1:
                obstacle1.rect.x = (random.randint(300, 900))
                all_sprites_list.remove(obstacle2)
                obstacle2.kill()
            if o == 2:
                obstacle1.rect.x = (random.randint(300, 900))
                obstacle2.rect.x = (random.randint(300, 900))
                if obstacle2.rect.x - obstacle1.rect.x > 0:
                    while obstacle1.rect.x - obstacle2 .rect.x < 100:
                        obstacle1.rect.x = (random.randint(300, 900))
                        obstacle2.rect.x = (random.randint(300, 900))
class Obstacle1(pygame.sprite.Sprite):
    
    def __init__(self, color, x, y, width, weight,):
        super().__init__()
        self.color = color
        self.image = pygame.Surface([width, weight])
        self.image.fill(color)
        self.rect = self.image.get_rect()
        self.rect.x = x
        self.rect.y = y


class Obstacle2(pygame.sprite.Sprite):
    
    def __init__(self, color, x, y, width, weight,):
        super().__init__()
        self.color = color
        self.image = pygame.Surface([width, weight])
        self.image.fill(color)
        self.rect = self.image.get_rect()
        self.rect.x = x
        self.rect.y = y
            

                
#main

color_line = (0,0,0)

pygame.init()
screen = pygame.display.set_mode([1000, 500])

all_sprites_list = pygame.sprite.Group()

player_width  = 50
player_weight = 50

player = Player(RED, 0, 413, 50, 50)
if o == 1:
    obstacle1 = Obstacle1(BLACK, random.randint(300, 900), 410 , 25, 100)
    all_sprites_list.add(obstacle1)
if o == 2:
    obstacle1 = Obstacle1(BLACK, random.randint(300, 900), 410 , 25, 100)
    obstacle2 = Obstacle2(BLACK, random.randint(300, 900), 410 , 25, 100)
    all_sprites_list.add(obstacle1)
    all_sprites_list.add(obstacle2)

all_sprites_list.add(player)

clock = pygame.time.Clock()

running = True
while running:

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
    #clicks

    keys = pygame.key.get_pressed()
    if isjump == False:
        #Up arrow key
        if keys[pygame.K_UP]:
            isjump = True    
            v = jump_v
        #W key
        if keys[pygame.K_w]:
            isjump = True    
            v = jump_v
        #Space bar
        if keys[pygame.K_SPACE]:
            isjump = True    
            v = jump_v
    else:
        m = 1 if v >= 0 else -1
        F = m * (v**2)
        player.rect.y -= F
        
        v -= 1
        if v < -jump_v:
            isjump = False
    
    #updates
    
    all_sprites_list.update()

    #draws
    
    screen.fill((255, 255, 255))

    pygame.display.set_caption('Jump game thing')

    pygame.draw.line(screen, color_line, (0, 500), (1000, 500), 75)
    
    all_sprites_list.draw(screen)

    pygame.display.flip()

    o = random.randint(0, 2)

    clock.tick(30)
    
pygame.quit()

Upvotes: 1

Views: 195

Answers (1)

Rabbid76
Rabbid76

Reputation: 211278

There is no need to call all_sprites_list.remove(). kill removes the sprite from all groups.

Create a separate pygame.sprite.Group for the obstacles and a function that removes all current obstacles and generates new obstacles:

all_sprites_list = pygame.sprite.Group()
obstacle_group = pygame.sprite.Group()

def create_new_obstacles():
    for obstacle in obstacle_group:
        obstacle.kill()
    o = random.randint(0, 1)+1
    if o > 0:
        obstacle1 = Obstacle(BLACK, random.randint(300, 900), 410 , 25, 100)
        obstacle_group.add(obstacle1)
        all_sprites_list.add(obstacle1)
    if o > 1:
        obstacle2 = Obstacle(BLACK, random.randint(300, 900), 410 , 25, 100)
        while abs(obstacle1.rect.x - obstacle2.rect.x) < 100:
             obstacle2 = Obstacle(BLACK, random.randint(300, 900), 410 , 25, 100)
        obstacle_group.add(obstacle2)
        all_sprites_list.add(obstacle2)

Use pygame.sprite.spritecollide to detect a collision of the player and an obstacle. Create new obstacles when a collision is detected:

class Player(pygame.sprite.Sprite):
    # [...]

    def update(self):
        self.rect.x += 7
        
        if pygame.sprite.spritecollide(self, obstacle_group, False):
            self.rect.x = 0
            create_new_obstacles()
        
        if self.rect.x >= 950:
            self.rect.x = 0
            create_new_obstacles()

The concept of classes is that you have 1 class but multiple objects with the same class type (see Classes). You don't need the classes Obstacle1 and Obstacle2. Obstacle is sufficient.

Complete example:

import pygame
import random

jump_v = 7     
isjump = False
v = 5
m = 1

GRAY = (192, 192, 192)
RED  = (255,   0,   0)
BLACK = (0 ,    0,   0)

class Player(pygame.sprite.Sprite):
    
    def __init__(self, color, x, y, width, weight):
        super().__init__()
        self.color = color
        self.image = pygame.Surface([width, weight])
        self.image.fill(color)
        self.rect = self.image.get_rect()
        self.rect.x = x
        self.rect.y = y

    def update(self):
        self.rect.x += 7
        
        if pygame.sprite.spritecollide(self, obstacle_group, False):
            self.rect.x = 0
            create_new_obstacles()
        
        if self.rect.x >= 950:
            self.rect.x = 0
            create_new_obstacles()

class Obstacle(pygame.sprite.Sprite): 
    def __init__(self, color, x, y, width, weight,):
        super().__init__()
        self.color = color
        self.image = pygame.Surface([width, weight])
        self.image.fill(color)
        self.rect = self.image.get_rect()
        self.rect.x = x
        self.rect.y = y

#main

color_line = (0,0,0)

pygame.init()
screen = pygame.display.set_mode([1000, 500])

player_width  = 50
player_weight = 50

def create_new_obstacles():
    for obstacle in obstacle_group:
        obstacle.kill()
    o = random.randint(0, 1)+1
    if o > 0:
        obstacle1 = Obstacle(BLACK, random.randint(300, 900), 410 , 25, 100)
        obstacle_group.add(obstacle1)
        all_sprites_list.add(obstacle1)
    if o > 1:
        obstacle2 = Obstacle(BLACK, random.randint(300, 900), 410 , 25, 100)
        while abs(obstacle1.rect.x - obstacle2.rect.x) < 100:
             obstacle2 = Obstacle(BLACK, random.randint(300, 900), 410 , 25, 100)
        obstacle_group.add(obstacle2)
        all_sprites_list.add(obstacle2)

all_sprites_list = pygame.sprite.Group()
obstacle_group = pygame.sprite.Group()
player = Player(RED, 0, 413, 50, 50)
create_new_obstacles()
all_sprites_list.add(player)

clock = pygame.time.Clock()

running = True
while running:

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
    #clicks

    keys = pygame.key.get_pressed()
    if isjump == False:
        #Up arrow key
        if keys[pygame.K_UP]:
            isjump = True    
            v = jump_v
        #W key
        if keys[pygame.K_w]:
            isjump = True    
            v = jump_v
        #Space bar
        if keys[pygame.K_SPACE]:
            isjump = True    
            v = jump_v
    else:
        m = 1 if v >= 0 else -1
        F = m * (v**2)
        player.rect.y -= F
        
        v -= 1
        if v < -jump_v:
            isjump = False
    
    #updates
    
    all_sprites_list.update()

    #draws
    
    screen.fill((255, 255, 255))

    pygame.display.set_caption('Jump game thing')

    pygame.draw.line(screen, color_line, (0, 500), (1000, 500), 75)
    
    all_sprites_list.draw(screen)

    pygame.display.flip()

    clock.tick(30)
    
pygame.quit()

Upvotes: 1

Related Questions