如何从python中的列表中正确删除sprite?

时间:2013-11-16 05:15:18

标签: python list pygame sprite

我有一个游戏,上面有“橘子”和“女巫,精灵和上课”的“MyGame”。在“MyGame”课程的“绘画”中,当用户点击女巫时,游戏会画出橘子和女巫,我需要从列表中删除女巫,所以它应该从屏幕上消失。我已经这样做了,问题是它从列表中删除了所有女巫,不仅仅是其中一个,在某些情况下,我只是拥有所有它们从屏幕上消失了,而另一个我有:

Traceback (most recent call last):
File "mygame.py", line 219, in <module>
MyGame().run()
File "mygame.py", line 155, in run
self.draw()
File "mygame.py", line 175, in draw
self.witches[i].draw(self.screen)
IndexError: list index out of range.

这是我的代码:

class MyGame(object):
    def __init__(self):
        """Initialize a new game"""
        pygame.mixer.init()
        pygame.mixer.pre_init(44100, -16, 2, 2048)

        self.witches = []
        for x in xrange(2):
            position = self.width//2, self.height//2
            self.witches.append(Witch(position, self.witch))

        self.pos = 0, 0
    def draw(self):
        """Update the display"""
        # everything we draw now is to a buffer that is not displayed
        self.screen.fill(self.bg_color)
       for i in self.oranges:
            i.draw(self.screen)

        if len(self.witches) >= 2:
            for i in range(len(self.witches)):
                self.witches[i].draw(self.screen)
                if int(self.witches[i].position[1]) in range(250,350):
                    for o in self.oranges:
                        self.oranges.remove(o)

                if self.pos[0] in range (int(self.witches[i].position[0]-30), (int(self.witches[i].position[0])+30) \
                    or self.pos[1] in range ((int(self.witches[i].position[1])-30), (int(self.witches[i].position[1])+30))):
                        for w in self.witches:
                            print "witches out"
                            self.witches.remove(w)

P.S。我是初学者,有人能解释一下吗?我会非常感激

1 个答案:

答案 0 :(得分:3)

让我们关注发生错误的for循环:

for i in range(len(self.witches)):
    self.witches[i].draw(self.screen)
    if int(self.witches[i].position[1]) in range(250,350):
        for o in self.oranges:
            self.oranges.remove(o)

    if self.pos[0] in range (int(self.witches[i].position[0]-30), (int(self.witches[i].position[0])+30) \
        or self.pos[1] in range ((int(self.witches[i].position[1])-30), (int(self.witches[i].position[1])+30))):
        for w in self.witches:
            print "witches out"
            self.witches.remove(w)

如果我们再削减你的代码,它基本上是这样做的:

for i in range(len(self.witches)):
    self.witches[i].draw(self.screen)

    # Do stuff with oranges

    if some_conditions_are_true:
        for w in self.witches:
            print "witches out"
            self.witches.remove(w)

正在发生的事情是,在某些情况下,您要从self.witches列表中删除女巫。但是,顶部for循环仍在迭代range(len(self.witches)) - 它没有意识到巫婆的数量已经发生变化,因此它仍在迭代原始数量。

一旦删除了一个女巫,for-loop将继续迭代超出列表范围。

此外,for循环将删除每个女巫,而不仅仅是一个接近玩家的女巫。

以下是我修复代码的方法:

alive_witches = []

# This kind of for-loop lets you grab each element from a list. 
# It's identical to how you were grabbing each witch before, but is cleaner to read
for witch in self.witches:   
    witch.draw(self.screen)

    # Do stuff with oranges

    witch_x = witch.position[0]
    witch_y = witch.position[1]
    close_to_player_x = witch_x - 30 <= self.pos[0] <= witch_x + 30
    close_to_player_y = witch_y - 30 <= self.pos[1] <= witch_y + 30

    if not (close_to_player_x or close_to_player_y):
        # Save the witches that are not dead
        alive_witches.append(witch)

# Save the witches that are still alive
self.witches = alive_witches

查看您的代码,您的橘子可能会遇到类似的问题。在这种情况下,我会把它作为练习让你弄清楚如何解决它。