Shoot problem: How to show a bullet before shoot?

Question:

I would like the ‘banana’ to be shown when the space bar is pressed, while it follows the character movement, and then to be fired upon the release of the same.

    import pygame
    from pygame.locals import *
    
    
    #inizializzazione
    pygame.init()
    screen=pygame.display.set_mode((400,750))
    pygame.display.set_caption('MonkeyBanana')
    FPS=60
    
    
    
    #load image
    img_ground = pygame.image.load('Surf/sfondo.jpg').convert_alpha()
    surf_ground=pygame.transform.scale(img_ground,(img_ground.get_width(),screen.get_height()))
    
    
    class Monkey (pygame.sprite.Sprite):
        def __init__(self):
            super().__init__()
            self.sprites = [pygame.transform.scale((pygame.image.load('Surf/Animazioni/monkey_idle_00.png').convert_alpha()),
                                                   (screen.get_width() / 5, screen.get_height() / 7)),
                            pygame.transform.scale((pygame.image.load('Surf/Animazioni/monkey_idle_01.png').convert_alpha()),
                                                   (screen.get_width() / 5, screen.get_height() / 7)),
                            pygame.transform.scale((pygame.image.load('Surf/Animazioni/monkey_idle_02.png').convert_alpha()),
                                                   (screen.get_width() / 5, screen.get_height() / 7)),
                            pygame.transform.scale((pygame.image.load('Surf/Animazioni/monkey_idle_03.png').convert_alpha()),
                                                   (screen.get_width() / 5, screen.get_height() / 7))
                            ]
    
            self.launch_monkey=[]
            for i in range(0, 19):
                filename = "Surf/Animazioni/monkey_{:0>3}.png".format(i)
                img = pygame.image.load(filename).convert_alpha()
                img_reduced = pygame.transform.scale(img, (screen.get_width() / 5, screen.get_height() / 7))
                self.launch_monkey.append(img_reduced)
    
            self.count=0
            self.count1 = 0
    
    
            self.image = self.sprites[self.count]
            self.rect = self.image.get_rect()
            self.rect.midbottom = (screen.get_width() / 2, screen.get_height())
            all_sprites.add(self)
    
        def update(self):
            self.count += 0.08
            if self.count >= 3:
                self.count = 0
            self.image = self.sprites[int(self.count)]
            if move_right and monkey.rect.right < screen.get_width():
                monkey.rect.x += 5
            elif move_left and monkey.rect.left > 0:
                monkey.rect.x -= 5
    
        def launch(self):
            global launch
    
            if launch:
                self.count1 += 1
                if self.count1 >= 19:
                    self.count1 = 0
                    launch = False
                self.image = self.launch_monkey[int(self.count1)]
    
    
    class Banana (pygame.sprite.Sprite):
        def __init__(self):
            super().__init__()
            self.image= pygame.transform.scale((pygame.image.load('Surf/banana.png').convert_alpha()),
                                               (screen.get_width() / 10, screen.get_height() / 15))
            self.rect=self.image.get_rect()
            self.rect.center = monkey.rect.center
            all_banana.add(self)
    

here is the problem. Everything works fine on the first launch. The second time I press the space bar, the banana returns to the character’s hands instead of continuing the run.

        def update(self):
            global new_banana
            if keep_banana:
                self.rect.center = monkey.rect.center
                new_banana=False
    
            if launch_banana:
                self.rect.y -= 5
    
            if self.rect.top<50:
                self.kill()
    
    
    #create sprite and Group
    
    all_sprites = pygame.sprite.Group()
    all_banana= pygame.sprite.Group()
    monkey=Monkey()
    
    
    #other variables
    move_right=False
    move_left=False
    launch=False
    launch_banana=False
    keep_banana=False
    new_banana=False
    
    
    
    #principal cicle
    done=False
    while not done:
    
        for ev in pygame.event.get():
            if ev.type == QUIT:
                done = True
            if ev.type ==KEYDOWN:
                if ev.key== K_RIGHT:
                    move_right=True
                    idle = False
                if ev.key== K_LEFT:
                    move_left = True
                    idle = False
                if ev.key==K_SPACE:
                    keep_banana = True
                    new_banana=True
    
            elif ev.type ==KEYUP:
                if ev.key== K_RIGHT:
                    move_right=False
                    idle = True
                if ev.key== K_LEFT:
                    move_left=False
                    idle = True
                if ev.key==K_SPACE:
                    launch_banana=True
                    keep_banana = False
                    launch = True
    
        #Game logic
        if new_banana:
            banana=Banana()
    
        #screen update
    
    
        screen.blit(surf_ground, (0, 0))
        all_sprites.draw(screen)
        all_banana.draw(screen)
        all_banana.update()
        all_sprites.update()
        monkey.launch()
        pygame.display.flip()
        pygame.time.Clock().tick(FPS)
    
    #end principal cicle
    pygame.quit()

It works to me in another version without classes,by adding the banana to a new group every time it is fired, but I can’t get it to work on the classes. I have tried so many times, but nothing seems to work

Asked By: redanol

||

Answers:

launch_banana makes the banana fly:

if launch_banana:
   self.rect.y -= 5

launch_banana is False at the beginning, but it is never set False again once it has become True. You have to set launch_banana to False when keep_banana is set True:

launch_banana=False
keep_banana=False
new_banana=False

# [...]

while not done:

    for ev in pygame.event.get():
        # [...]

        if ev.type == KEYDOWN:
            # [...]

            if ev.key == K_SPACE:
                launch_banana = False        # <---
                keep_banana = True
                new_banana = True

        elif ev.type == KEYUP:
            # [...]

            if ev.key == K_SPACE:
                launch_banana = True
                keep_banana = False
                launch = True

Anyway, instead of all these Boolean variables, I propose to add a state to the Banana class. The state can be "keep" at the beginning and can be changed to "launched" after the banana is started.

class Banana (pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.image= pygame.transform.scale((pygame.image.load('Surf/banana.png').convert_alpha()),
                                               (screen.get_width() / 10, screen.get_height() / 15))
        self.rect=self.image.get_rect()
        self.rect.center = monkey.rect.center
        all_banana.add(self)

        self.state = "keep"

    def start(self):
        self.state = "launched"

    def update(self):
        if self.state == "keep":
            self.rect.center = monkey.rect.center
    
        elif self.state == "launched":
            self.rect.y -= 5
    
        if self.rect.top<50:
            self.kill()
Answered By: Rabbid76

Thanks for the reply

So

implement the launch_banana= False in Space Keydown don’t work:

     if ev.key == K_SPACE:
            launch_banana = False        # <---
            keep_banana = True
            new_banana = True

I implemented the banana states in this way in the game logic and work fine, by creating 2 sprite group:

        import pygame
        from pygame.locals import *


        #inizializzazione
        pygame.init()
        screen=pygame.display.set_mode((400,750))
        pygame.display.set_caption('MonkeyBanana')
        FPS=60



        #load image
        img_ground = pygame.image.load('Surf/sfondo.jpg').convert_alpha()
        surf_ground=pygame.transform.scale(img_ground,(img_ground.get_width(),screen.get_height()))


        class Monkey (pygame.sprite.Sprite):
            [...]

        class Banana(pygame.sprite.Sprite):
            def __init__(self):
                super().__init__()
                self.image = pygame.transform.scale((pygame.image.load('Surf/banana.png').convert_alpha()),
                                                    (screen.get_width() / 10, screen.get_height() / 15))
                self.rect = self.image.get_rect()
                self.rect.center = monkey.rect.center
                one_banana.add(self)   <-------------GroupSingle

                self.state = "keep"


            def start(self):
                self.state = "launched"

            def update(self):
                if self.state == "keep":
                    self.rect.center = monkey.rect.center

                elif self.state == "launched":
                    self.rect.y -= 5

                if self.rect.top < 50:
                    self.kill()


        #create sprite and Group

        all_sprites = pygame.sprite.Group()
        all_banana= pygame.sprite.Group()
        one_banana= pygame.sprite.GroupSingle() <------add this group
        monkey=Monkey()


        #other variables
        move_right=False
        move_left=False
        launch=False
        launch_banana=False
        keep_banana=False
        new_banana=False



        #principal cicle
        done=False
        while not done:

            for ev in pygame.event.get():
                if ev.type == QUIT:
                    done = True
                if ev.type ==KEYDOWN:
                    if ev.key== K_RIGHT:
                        move_right=True
                        idle = False
                    if ev.key== K_LEFT:
                        move_left = True
                        idle = False
                    if ev.key==K_SPACE:
                        keep_banana = True
                        new_banana=True

                elif ev.type ==KEYUP:
                    if ev.key== K_RIGHT:
                        move_right=False
                        idle = True
                    if ev.key== K_LEFT:
                        move_left=False
                        idle = True
                    if ev.key==K_SPACE:
                        launch_banana=True
                        keep_banana = False
                        launch = True

            #Game logic
            **if new_banana:
                banana=Banana()
                if launch_banana:
                    one_banana.empty()
                    all_banana.add(banana)   <------The new logic works
                    banana.start()
                    launch_banana=False
                    new_banana=False**



            #screen update


            screen.blit(surf_ground, (0, 0))
            all_sprites.draw(screen)
            all_banana.draw(screen)
            one_banana.draw(screen)
            one_banana.update()
            all_banana.update()
            all_sprites.update()
            monkey.launch()
            pygame.display.flip()
            pygame.time.Clock().tick(FPS)

        #end principal cicle
        pygame.quit()

There is a way much simple to do this?
Thank you in any case

Answered By: redanol
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.