formalhalt
formalhalt

Reputation: 11

How do I make a pygame sprite "shoot" another out

I'm trying to make the ladybug sprite shoot out the egg sprite whenever a condition is true

In this case that condition would be when the ladybug sprite hits the leaf sprites

I've managed to make that sort of happen but I'm unable to have it repeat it self It is only shooting once, I've tried a few different ways to make it work but I have been unsuccessful.

import pygame
import sys
import random

pygame.init()
res = (1000, 600)
pygame.display.set_caption("placeholder")
screen = pygame.display.set_mode(res)
worldbg = pygame.image.load("worldbg.png").convert_alpha()

clock = pygame.time.Clock()

class Egg(pygame.sprite.Sprite):

    def __init__(self, x, y):
        pygame.sprite.Sprite.__init__(self)
        self.x = random.randint(1, 1000)
        self.y = random.randint(1, 600)
        self.x_speed = 0.2
        self.y_speed = 0.2
        self.x_direction = 1
        self.y_direction = 1

        self.frame = 0
        super().__init__()
        self.sprites = []
        self.is_animating = False

        self.sprites.append(pygame.image.load("egg.png"))
        self.sprites.append(pygame.image.load("egg.png"))
        self.sprites.append(pygame.image.load("egg.png"))
        self.sprites.append(pygame.image.load("egg.png"))



        self.current_sprite = 0
        self.image = self.sprites[self.current_sprite]

        self.rect = self.image.get_rect()
        self.rect.center = [x, y]

    def animate(self):
        self.is_animating = True

    def kill(self):
        pygame.sprite.Sprite.kill(self)

    def update(self):
        if self.is_animating:
            self.current_sprite += 0.20
            if self.current_sprite >= len(self.sprites):
                self.current_sprite = 0
                self.is_animating = False
        self.image = self.sprites[int(self.current_sprite)]

# this makes the bullet act like a heatsinking missile

        if self.x < player.rect.x + 40:
            self.x_direction = 8
            self.x_direction = 4
        elif self.x > player.rect.x + 40:
            self.x_direction = -8
            self.x_direction = -4

        if self.y > player.rect.y + 40:
            self.y_direction = -8
            self.y_direction = -4

        elif self.y < player.rect.y + 40:
            self.y_direction = 8
            self.y_direction = 4

        self.x_speed = random.randint(1, 2) * self.x_direction
        self.y_speed = random.randint(1, 2) * self.y_direction

        self.x += self.x_speed
        self.y += self.y_speed
        self.rect.x = self.x
        self.rect.y = self.y



        self.rect.clamp_ip(screen.get_rect())

eggmis = False
lvl4 = True
lvl4sr = 0

ladybug = Ladybug(0, 0)
ladybug_sprites = pygame.sprite.Group()
ladybug_sprites.add(ladybug)
ladybug.rect.x = 0
ladybug.rect.y = 0
ladybug.list = pygame.sprite.Group()
ladybug.list.add(ladybug)

egg = Egg(0, 0)
egg_sprites = pygame.sprite.Group()
egg_sprites.add(egg)
egg.rect.x = 0
egg.rect.y = 0
egg.list = pygame.sprite.Group()
egg.list.add(egg)


 # while loop starts here but I'll skip that

 if lvl4sr >= 12:
        lvl4 = True

    if lvl4 is True:



        chl = pygame.sprite.spritecollide(ladybug, leaf_sprites, False, pygame.sprite.collide_circle_ratio(0.2))
        if chl:
            playerhp -= 20
            eggmis = True
          
   if eggmis is True:

        ehp = pygame.sprite.collide_circle(egg, player)
        if ehp is True:
            pygame.sprite.Sprite.kill(egg)

        egg_sprites.draw(screen)
        egg_sprites.update()
        lvl4sr -= 6

this makes the bullet fires one time once the condition is reached then doesn't work

Upvotes: 1

Views: 40

Answers (1)

Kingsley
Kingsley

Reputation: 14906

Here's one typical approach for implementing this "create & animate a transient object" type problem:

egg_list = []    # all eggs are held in this list/spritegroup/whatever

### main loop

# Update all entities:
for egg in egg_list:
    egg.update()                          # move every egg by their (dx, dy)

# Handle collisions
for egg in egg_list:                      # collide every egg
    if ( egg.collideswith( player ) ):
        # remove egg from egg_list        # the egg is 'used up'
        # do some stuff to player

# Paint the screen
background.draw( window )
player.draw( window )
for egg in egg_list:                      # paint every egg to the window
    egg.draw( window )    

Note that we never handle a specific egg arbitrarily. It's always handling whatever egg is found in egg_list. It doesn't matter if egg_list is a Sprite Group, list, dictionary, whatever - the same program flow is used. The take-away point is that don't care how many eggs are in the list, we process all of them, in turn, the same way.

The benefit of this approach, is that now all egg handling is done as a batch. So now when an egg object is created, it will automatically be moved, painted, animated etc.

So when your LadyBug object collides with a Leaf object, we can just add a new egg to the egg_list.

if ( ladybug.collideswith( leaf ) ):
    egg_list.append( Egg( ladybug.x, ladybug.y, ... ) )   # create an egg

Your code is not handling the updating of egg objects as a batch, and it is not creating a new egg when the ladybird collides with the leaf.

Obviously the Sprite Group automates a lot of this for you, in particular the updating, colliding and drawing. But you need the supporting code to properly use those functions. Maybe you had all this, but didn't add it to the question.

Upvotes: 1

Related Questions