Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pygame remove a single sprite from a group

I am making a game and when the sprite goes under 100 on the x axis it is supposed to be deleted. The sprites are all located in a class. When the first sprite reaches the end, it deletes the final sprite of the group instead of the first.

Enemy Class

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)

Main Loop (Part for enemy)

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

I have a background and everything else works fine, I just cannot delete the correct sprite from the enemy group.

like image 567
Steve104 Avatar asked Nov 16 '16 12:11

Steve104


People also ask

How do I remove a sprite from a group in pygame?

The kill() method removes the sprite from all groups it belongs to. This will cleanly delete the sprite object.

How do I remove an object from pygame?

In pygame your objects should usually be subclasses of pygame. sprite. Sprite and should be stored in sprite groups which allow you to update and render all contained sprites by calling the update and draw methods. You can remove the sprites from the corresponding groups by calling their kill method.

How do I empty a group in pygame?

Yes, simple: pygame. sprite. Group(). empty() will do it.


2 Answers

An easier way would be to use the Sprite method kill() which removes a sprite from all pygame.sprite.Group´s it's currently in.

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

Calling die() in your update() will allow you to check whether to kill your sprite every game loop, but given the amount of code in die() you could simply just move the code inside the update(). And based on your current code, your EnemyList is already a pygame.sprite.Group object, so no change is needed there.

Your current die() method is quite hard for me to comprehend. You're creating an enemy which checks whether all enemies (itself and the other in the list) should die. So in your game loop you call the method from a single enemy in order to control all enemies. In other words, you're creating identical objects with different responsibilities. As a rule of thumb: an object's methods should change only its own states.

Lastly, the draw() method is unnecessary since the superclass defines the method exactly in the way you have. So removing yours would instead call draw() of pygame.sprite.Sprite.

like image 182
Ted Klein Bergman Avatar answered Oct 05 '22 00:10

Ted Klein Bergman


You cannot remove items from a list while iterating over it:

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

You could instead write something like this:

def die(self):
     global EnemyList
     EnemyList = [enemy for enemy in EnemyList if enemy.rect.x>=100]

The global statement is needed so that the function can modify the EnemyList, which is outside its scope in this case.

Or store the enemies that you want to delete to another list, and then delete them afterwards.

like image 31
J. P. Petersen Avatar answered Oct 05 '22 01:10

J. P. Petersen