Pygame如何从一个组中移除单个精灵?

5
我正在制作一款游戏,当精灵在x轴下降到100以下时,它应该被删除。所有精灵都位于一个类中。当第一个精灵到达终点时,它会删除组中的最后一个精灵,而不是第一个。
敌人类
class Enemy(pygame.sprite.Sprite): 
    def __init__(self,x,y):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.image.load('Enemy.gif').convert()
        self.rect = self.image.get_rect(x=x, y=y)

    def update(self):
       self.rect.x -= 4

    def die(self):
        for enemy in EnemyList:
            if enemy.rect.x<100:
                 EnemyList.remove(enemy)

    def draw(self, DISPLAY):
        DISPLAY.blit(self.image, self.rect)

主循环(敌人部分)

time = 0
while not Gameover: #Loop of the gameplay
if time in (0,50,100,150,200):
    enemy = Enemy(DIS_HEIGHT,random.randrange(0,DIS_HEIGHT)
    enemy.add(EnemyList)
EnemyList.update()
EnemyList.draw(DISPLAY)
enemy.die()
time +=1

我有相关背景,其他一切都正常,只是无法从敌人组中删除正确的精灵。

2个回答

9
一个更简单的方法是使用Sprite方法kill(),该方法将从其当前所在的所有pygame.sprite.Group中删除精灵。
def die(self):
    if self.rect.x < 100:
        self.kill()

在您的update()中调用die()函数可以让您在每个游戏循环中检查是否要销毁精灵,但是考虑到die()函数中的代码量,您可以将其中的代码移动到update()函数中。鉴于您当前的代码,您的EnemyList已经是一个pygame.sprite.Group对象,因此无需更改。
您当前的die()方法对我来说很难理解。您正在创建一个敌人来检查所有敌人(自身和列表中的其他敌人)是否应该死亡。因此,在游戏循环中,您从单个敌人中调用该方法以控制所有敌人。换句话说,您正在创建具有不同职责的相同对象。作为一条经验法则:对象的方法应仅更改其自身状态。
最后,draw()方法是不必要的,因为超类已经以您所期望的方式定义了该方法。因此,删除您的draw()方法将调用pygame.sprite.Spritedraw()方法。

是的,使用“kill”是正确的方法。但为什么不直接将此检查移至更新函数中呢? - sloth
我想如果我们想添加更多的检查,将它们分开可能是个好主意,但考虑到当前的代码量,直接放在“update”方法中可能会更好。我会编辑它,谢谢! - Ted Klein Bergman

4

当您对列表进行迭代时,您不能从中删除元素:

def die(self):
    for enemy in EnemyList:
        if enemy.rect.x<100:
             EnemyList.remove(enemy)

您可以改为写成这样:

您可以尝试像这样编写:

def die(self):
     global EnemyList
     EnemyList = [enemy for enemy in EnemyList if enemy.rect.x>=100]
< p > 在这种情况下,需要使用 global 语句来使函数能够修改在其作用域之外的 EnemyList

或者将要删除的敌人存储到另一个列表中,然后再进行删除。


无法工作,我收到了以下错误信息 Traceback (most recent call last): File "F:\Game.py", line 203, in <module> enemy.die() File "F:\Game.py", line 53, in die EnemyList = [enemy for enemy in EnemyList if enemy.rect.x<100] UnboundLocalError: 对未赋值的本地变量 'EnemyList' 进行了引用 - Steve104
我假设EnemyList是一个已定义的变量,因为你发布的代码已经使用了它。 - J. P. Petersen
抱歉 :) 我忘记了一个全局声明。我会更新答案。 - J. P. Petersen
1
我是这样做的:return [EnemyList.remove(enemy) for enemy in EnemyList if enemy.rect.x<100] - Steve104
我现在已经更新了答案。另一个没有使用 global 语句的解决方案是 EnemyList[:] = ... - J. P. Petersen
如果您觉得我的回答有用,能否接受并采纳呢? :) - J. P. Petersen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接