Your first problem is that you use a for...else loop; and the else part will be executed if you don't break the for loop in case of a collision, and thus re-adding the sprite.
The second problem with your code is that while groupcollide will correctly remove the sprites from their groups, they will be readded since they are still stored in the list you're iterating over with your for loop (iterating over a sprite group will create a new list every time).
So you can either fix your code with something like this:
for mob in mobs.sprites():
if not mob.groups():
# mob was already removed by a previous iteration of this loop
continue
temp_sprites.add(mob)
mobs.remove(mob)
collision = pygame.sprite.groupcollide(temp_sprites, mobs, True, True)
for col in collision:
# score is just for the game
score += col.size
break
else:
mobs.add(mob)
all_sprites.add(mob)
temp_sprites.remove(mob)
but I would suggest to handle the collision in the update method of the sprite instead.
def update(self):
# whatever
if pygame.sprite.spritecollide(self, self.mobs, True, collide_rect_not_self):
self.kill()
where self.mobs is a reference to the mobs group and collide_rect_not_self is a simple wrapper around pygame.sprite.collide_rect:
def collide_rect_not_self(a, b):
if a != b:
return pygame.sprite.collide_rect(a, b)
Here's a full example:
import random
import pygame
def collide_rect_not_self(a, b):
if a != b:
return pygame.sprite.collide_rect(a, b)
class Actor(pygame.sprite.Sprite):
def __init__(self, pos, mobs, static, *grps):
super().__init__(mobs, *grps)
self.image = pygame.Surface((40, 40))
self.rect = self.image.get_rect(center=pos)
self.pos = pygame.Vector2(*pos)
self.vel = pygame.Vector2(random.randint(0, 10), random.randint(0, 10)) if not static else pygame.Vector2(0, 0)
self.mobs = mobs
def update(self):
self.pos += self.vel
if not pygame.display.get_surface().get_rect().contains(self.rect):
self.vel *= -1
self.rect.clamp_ip(pygame.display.get_surface().get_rect())
self.pos = self.rect.center
self.rect.center = self.pos
if pygame.sprite.spritecollide(self, self.mobs, True, collide_rect_not_self):
self.kill()
def main():
pygame.init()
clock = pygame.time.Clock()
screen = pygame.display.set_mode((800, 600))
mobs = pygame.sprite.Group()
all_sprites = pygame.sprite.Group()
while True:
for event in pygame.event.get():
pos = pygame.mouse.get_pos()
if event.type == pygame.QUIT:
return
if event.type == pygame.MOUSEBUTTONDOWN:
Actor(event.pos, mobs, event.button == 1, all_sprites)
screen.fill((255, 255, 255))
all_sprites.update()
all_sprites.draw(screen)
clock.tick(30)
pygame.display.flip()
main()
Use the left mouse button to place a static rect and the other mouse buttons to place a moving one.
