Why is self.kill() not removing the object from the group?
Question:
I’ve asked this question a while ago but the answers weren’t entirely helpful and I don’t believe I posted a minimum reproducible example. I’m trying to kill my bullet after some time (self.lifetime) has passed. The self.kill() command is executed, but it does not remove the bullet from the camera group, which is what I use to draw all bullets.
The relevant code:
Player.shoot():
def shoot(self, pos):
self.current_time = pg.time.get_ticks()
# Allow the player to shoot (but not continuously)
if not self.shooting and self.current_time - self.last_shot_time >= self.shoot_cooldown:
self.last_shot_time = self.current_time
# Setting self.shooting to True so that only one bullet is created
self.shooting = True
# Creating the bullet
bullet = Bullet(self.rect.centerx, self.rect.centery, "bullet", pos, 2, a_s.camera)
# Reset self.shooting
self.shooting = False
Bullet.update():
def update(self):
# Killing the bullet after self.lifetime has passed
if pg.time.get_ticks() - self.start_time > self.lifetime:
self.kill()
print("Killing")
# Moving the bullet (accurately, self.x is float while self.rect.x can only be int)
self.x += self.vel_x
self.y += self.vel_y
self.rect.x = int(self.x)
self.rect.y = int(self.y)
Entity class: (bullet inherits from this)
class Entity(pg.sprite.Sprite):
def __init__(self, speed, group):
pg.sprite.Sprite.__init__(self)
self.speed = speed
group.add(self)
I’m also adding a pastebin to allow you to reproduce this example, however you will need 3 images titled "ground.png", "player.png", and "bullet.png" in the directory to run it.
Pastebin: https://pastebin.com/Vi57HF1i
Images I use (credit to someone else, not sure where I got them from): https://imgur.com/a/Oqp4lWq
Answers:
The problem has to do with the Multiple Inheritance. Each * Bullet
has 2 base classes which are derived from pygame.sprite.Sprite
So each Bullet
actually consists of 2 sprites. This is not intentional and cause kill not to work. When you call kill
, just the "first" pygame.sprite.Sprite
object is removed from the Groups.
The problem can be reproduced with the following minimal example:
import pygame
elementGroup = pygame.sprite.Group()
entityGroup = pygame.sprite.Group()
class Element(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
elementGroup.add(self)
class Entity(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
entityGroup.add(self)
class Bullet(Element, Entity):
def __init__(self):
Entity.__init__(self)
Element.__init__(self)
bullet = Bullet()
print(len(elementGroup), len(entityGroup))
bullet.kill()
print(len(elementGroup), len(entityGroup))
Output:
1 1
0 1
To solve the problem, you need to restructure your code. Each class should be derived from pygame.sprite.Sprite
only once.
I’ve asked this question a while ago but the answers weren’t entirely helpful and I don’t believe I posted a minimum reproducible example. I’m trying to kill my bullet after some time (self.lifetime) has passed. The self.kill() command is executed, but it does not remove the bullet from the camera group, which is what I use to draw all bullets.
The relevant code:
Player.shoot():
def shoot(self, pos):
self.current_time = pg.time.get_ticks()
# Allow the player to shoot (but not continuously)
if not self.shooting and self.current_time - self.last_shot_time >= self.shoot_cooldown:
self.last_shot_time = self.current_time
# Setting self.shooting to True so that only one bullet is created
self.shooting = True
# Creating the bullet
bullet = Bullet(self.rect.centerx, self.rect.centery, "bullet", pos, 2, a_s.camera)
# Reset self.shooting
self.shooting = False
Bullet.update():
def update(self):
# Killing the bullet after self.lifetime has passed
if pg.time.get_ticks() - self.start_time > self.lifetime:
self.kill()
print("Killing")
# Moving the bullet (accurately, self.x is float while self.rect.x can only be int)
self.x += self.vel_x
self.y += self.vel_y
self.rect.x = int(self.x)
self.rect.y = int(self.y)
Entity class: (bullet inherits from this)
class Entity(pg.sprite.Sprite):
def __init__(self, speed, group):
pg.sprite.Sprite.__init__(self)
self.speed = speed
group.add(self)
I’m also adding a pastebin to allow you to reproduce this example, however you will need 3 images titled "ground.png", "player.png", and "bullet.png" in the directory to run it.
Pastebin: https://pastebin.com/Vi57HF1i
Images I use (credit to someone else, not sure where I got them from): https://imgur.com/a/Oqp4lWq
The problem has to do with the Multiple Inheritance. Each * Bullet
has 2 base classes which are derived from pygame.sprite.Sprite
So each Bullet
actually consists of 2 sprites. This is not intentional and cause kill not to work. When you call kill
, just the "first" pygame.sprite.Sprite
object is removed from the Groups.
The problem can be reproduced with the following minimal example:
import pygame
elementGroup = pygame.sprite.Group()
entityGroup = pygame.sprite.Group()
class Element(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
elementGroup.add(self)
class Entity(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
entityGroup.add(self)
class Bullet(Element, Entity):
def __init__(self):
Entity.__init__(self)
Element.__init__(self)
bullet = Bullet()
print(len(elementGroup), len(entityGroup))
bullet.kill()
print(len(elementGroup), len(entityGroup))
Output:
1 1 0 1
To solve the problem, you need to restructure your code. Each class should be derived from pygame.sprite.Sprite
only once.