I am trying to permanently 'kill' targets when hit with a bullet but they re-appear after using '.kill()' (PYGAME)

Viewed 110

I have uploaded quite a few questions recently and I think people are getting tired of me but I am bad at programming and am trying to code a game for A-level coursework so I need all the help I can get to learn the language. Anyway, I'll show a few relevant bits of code below for reference. I use all_targets because I want to add delay using threshold so they don't all spawn simultaneously. I think this is causing the targets to be re-added to the sprite group but I can't resolve it. I want targets to be removed from target_sprites when hit with a bullet. I have tried using booleans to make it so that if destroyed == True: all_bullets.remove(item) but it does not seem to work. Any help is appreciated.

class Target(pygame.sprite.Sprite):
    def __init__(self, width, height, offset, threshold):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.Surface([width, height])
        self.image = target_img
        self.rect = self.image.get_rect()
        self.rect.center = (self.rect.x + 50, self.rect.y + offset)
        self.threshold = threshold



target_sprites = pygame.sprite.Group()

target_1 = Target(100, 100, 100, 0)
target_2 = Target(100, 100, 300, 150)
target_3 = Target(100, 100, 200, 300)
target_4 = Target(100, 100, 100, 450)
target_5 = Target(100, 100, 400, 600)
target_6 = Target(100, 100, 250, 750)

#Function to add delay between targets spawning.

def target_delay():
  global clock 
  clock += 1
  for item in all_targets:
    if clock >= item.threshold:
      target_sprites.add(item)

#Function to make targets move each time screen refreshes.
def movement():
  for item in target_sprites:
    item.rect.x += 1
  for item in all_bullets_keep:
    if item['y']-30 < (target_1.rect.y) + 100 and item['y']+30 > target_1.rect.y:
      if item['x']+10 > target_1.rect.x and item['x']-30 < (target_1.rect.x) + 100:
        target_1.kill()
    if item['y']-30 < (target_2.rect.y) + 100 and item['y']+30 > target_2.rect.y:
      if item['x']+10 > target_2.rect.x and item['x']-30 < (target_2.rect.x) + 100:
        target_2.kill()
    if item['y']-30 < (target_3.rect.y) + 100 and item['y']+30 > target_3.rect.y:
      if item['x']+10 > target_3.rect.x and item['x']-30 < (target_3.rect.x) + 100:
        target_3.kill()
    if item['y']-30 < (target_4.rect.y) + 100 and item['y']+30 > target_4.rect.y:
      if item['x']+10 > target_4.rect.x and item['x']-30 < (target_4.rect.x) + 100:
        target_4.kill()
    if item['y']-30 < (target_5.rect.y) + 100 and item['y']+30 > target_5.rect.y:
      if item['x']+10 > target_5.rect.x and item['x']-30 < (target_5.rect.x) + 100:
        target_5.kill()
    if item['y']-30 < (target_6.rect.y) + 100 and item['y']+30 > target_6.rect.y:
      if item['x']+10 > target_6.rect.x and item['x']-30 < (target_6.rect.x) + 100:
        target_6.kill()
2 Answers

You don't need the threshold attribute. Remove it:

class Target(pygame.sprite.Sprite):
    def __init__(self, width, height, offset):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.Surface([width, height])
        self.image = target_img
        self.rect = self.image.get_rect()
        self.rect.center = (self.rect.x + 50, self.rect.y + offset)

Create an empty sprite group:

target_sprites = pygame.sprite.Group()

The number of milliseconds since pygame.init() can be retrieved by pygame.time.get_ticks(). See pygame.time module. Use the ticks to spawn the sprites at interval in the main application loop (target_delay has to be called in the appliction loop):

offsets = [100, 300, 200, 100, 400, 150]
next_target_time = 0
threshold = 1000 # 1000 milliseconds = 1 second

def target_delay():
    global next_target_time, offsets
    current_time = pygame.time.get_ticks()
    if current_time > next_target_time and len(offsets) > 0:
        target_sprites.add(Target(100, 100, offsets[0]))
        offsets.pop(0)
        next_target_time = current_time + threshold

Evaluate if a target has to be killed (kill) in a loop:

for item in all_bullets_keep:
    for target in target_sprites:
        if item['y']-30 < (target.rect.y) + 100 and item['y']+30 > target.rect.y:
            if item['x']+10 > target.rect.x and item['x']-30 < (target.rect.x) + 100:
                target.kill()

I don't know if this helps, but there is a sprite function target_1.alive() that tells you whether the sprite has been killed or not. You can use this to detect first whether or not to draw it, and second, when all of them have been killed, so you know when to end the game.

Related