【问题标题】:Pygame remove a single sprite from a groupPygame 从组中删除单个精灵
【发布时间】:2017-03-30 16:02:50
【问题描述】:

我正在制作一个游戏,当精灵在 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

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

【问题讨论】:

    标签: python python-2.7 class pygame


    【解决方案1】:

    您不能在迭代列表时从列表中删除项目:

    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]
    

    需要global 语句,以便函数可以修改EnemyList,在这种情况下它超出了它的范围。

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

    【讨论】:

    • 它不起作用我得到错误 Traceback (最近一次调用最后): File "F:\Game.py", line 203, in enemy.die() File "F :\Game.py", line 53, in die EnemyList = [enemy for evidence in EnemyList ifenemy.rect.x
    • 我认为EnemyList 是一个已定义的变量,因为您发布的代码已经使用了它。
    • 抱歉 :) 忘记了全局声明。我会更新答案。
    • 我是这样做的
    • 我现在已经更新了答案。没有global 语句的另一个解决方案是EnemyList[:] = ...
    【解决方案2】:

    更简单的方法是使用 Sprite 方法 kill() 从所有 pygame.sprite.Group 中删除一个 sprite。

    def die(self):
        if self.rect.x < 100:
            self.kill()
    

    update() 中调用die() 将允许您检查是否在每个游戏循环中杀死您的精灵,但考虑到die() 中的代码量,您只需将代码移动到update() 中即可。根据您当前的代码,您的 EnemyList 已经是 pygame.sprite.Group 对象,因此无需更改。

    您当前的die() 方法我很难理解。您正在创建一个敌人,它检查是否所有敌人(自己和列表中的另一个)都应该死。因此,在您的游戏循环中,您从单个敌人调用该方法以控制所有敌人。换句话说,您正在创建具有不同职责的相同对象。根据经验:一个对象的方法应该只改变它自己的状态。

    最后,draw() 方法是不必要的,因为超类完全按照您的方式定义该方法。所以删除你的会改为调用draw() of pygame.sprite.Sprite

    【讨论】:

    • 是的,使用kill 是要走的路。但是为什么不简单地将这个检查移到更新函数中呢?
    • 我认为如果我们想添加更多检查,将它们分开可能会更好,但考虑到当前的代码量,最好将其直接放在 update 方法中。我会编辑它,谢谢!
    猜你喜欢
    • 1970-01-01
    • 2018-06-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多