为什么删除命令对我的 Pygame 精灵列表不起作用?

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

我正在 Pygame 中制作一个游戏,精灵刚好走到屏幕的尽头然后传送回来,并产生 1-2 个障碍物。当 1 个障碍物产生时,另一个障碍物仍然存在但不可见并结束游戏。即使我杀了它并将它从 sprite 列表中删除。我的代码有什么问题?

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()

不需要调用all_sprites_list.remove()kill 从所有组中删除精灵。

为障碍物创建一个单独的pygame.sprite.Group和一个移除所有当前障碍物并生成新障碍物的函数:

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)

使用pygame.sprite.spritecollide检测玩家与障碍物的碰撞。检测到碰撞时创建新障碍物:

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()

classes 的概念是您有 1 个 class 但多个具有相同 class 类型的对象(参见 Classes)。您不需要 classes Obstacle1Obstacle2Obstacle 就够了。

完整示例:

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()