3

I have a simple shooter game using pygame. I'm having some problems making the bullet's y coordinate slowly increasing up. I know this is something to do with the way I've programmed the Player class even though a bullet Rect is in it. I think I have to change the update function inside it. This is my code:

import pygame, random, sys, time

pygame.init()

#Constants
WIDTH = 800
HEIGHT = 500

BLACK = (0, 0, 0)
WHITE = (255, 255, 255) # Background Colour
RED = (255, 0, 0)
GREEN = (0, 255, 0)

window = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Pygame Shooter Game")

clock = pygame.time.Clock()
fps = 60

run = True

class Player():
    def __init__(self, width, colour, x, y):
        self.width = width
        self.colour = colour
        self.x = x
        self.y = y
        self.vel = 5
        self.shoot = False
        self.player = pygame.Rect(self.x, self.y, self.width, self.width)
        self.cartridge = pygame.Rect(0, 0, self.width/2, self.width/2)
        self.bullet = pygame.Rect(0, 0, 10, 20)
        self.shoot = False

    def draw(self, win):
        self.win = win
        pygame.draw.rect(self.win, self.colour, self.player) # Draw player(rect)
        pygame.draw.rect(self.win, GREEN, self.cartridge) #Draw cartridge
        if self.shoot:
            pygame.draw.rect(self.win, BLACK, self.bullet)
        
    def move(self):
        keys = pygame.key.get_pressed()

        if keys[pygame.K_LEFT] and self.x > 0: self.x -= self.vel # We don't do elif cuz we want them to be able to move diagonally
        if keys[pygame.K_RIGHT] and self.x < WIDTH-self.width: self.x += self.vel
        if keys[pygame.K_UP] and self.y > 0: self.y -= self.vel
        if keys[pygame.K_DOWN] and self.y < HEIGHT-self.width: self.y += self.vel

        if keys[pygame.K_SPACE]:
            self.shoot = True
    
    def update(self):
        self.player = pygame.Rect(self.x, self.y, self.width, self.width)
        self.cartridge.midbottom = self.player.midtop
        self.bullet.midbottom = self.cartridge.midtop

        if self.shoot:
            while self.bullet.y > 0:
                self.bullet.y -= 1

def main(win):
    run = True 

    player = Player(50, RED, WIDTH/2, HEIGHT/2)

    while run:
        win.fill(WHITE)
        clock.tick(fps)

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False

        player.move()
        player.update()
        player.draw(win)
        pygame.display.update()

    pygame.quit()
    sys.exit()

main(window)

Also, how can I make the create classes for each individual Cartridge and Bullet, to make the whole code more efficient?

1 Answers1

3

update is invoked continuously in the main application loop. Therefore, no additional animation loops are required for the update. Change the loop to a selection (change while to if):

while self.bullet.y > 0:

if self.bullet.y > 0:
    self.bullet.y -= 1

The starting position of the bullet must be set when the bullet is shot, rather than continuously when the bullet is updated:

class Player():
    # [...]

    def move(self):
        # [...]

        if keys[pygame.K_SPACE]:
            self.shoot = True
            self.bullet.midbottom = self.cartridge.midtop # <--- INSERT

    def update(self):
        self.player = pygame.Rect(self.x, self.y, self.width, self.width)
        self.cartridge.midbottom = self.player.midtop
        # self.bullet.midbottom = self.cartridge.midtop     <--- DELETE
        
        if self.shoot:
            if self.bullet.y > 0:                         # <--- if (not while)
                self.bullet.y -= 1

See also:

Rabbid76
  • 202,892
  • 27
  • 131
  • 174
  • Thanks a lot. Do you think I should change the Player class to involve only Player-related stuff, and so and so with a new Game class, Bullet and Cartridge? – TheCoder1343 Nov 02 '20 at 09:59
  • @TheCoder1343 Yes. Consider creating a `Bullet` class. Implement a bulleted list so that you can fire more than one bullet. The bullet should be fired by a `KEYDOWN` event rather than `pygame.key.get_pressed()`. See [What all things happens inside pygame when I press a key? When to use pygame.event==KEYDOWN](https://stackoverflow.com/questions/63050139/what-all-things-happens-inside-pygame-when-i-press-a-key-when-to-use-pygame-eve/63056690#63056690). – Rabbid76 Nov 02 '20 at 10:06
  • @TheCoder1343 But be careful `pygame.event.get()` should only be called once. See [Faster version of pygame.event.get()](https://stackoverflow.com/questions/58086113/faster-version-of-pygame-event-get/58087070#58087070) – Rabbid76 Nov 02 '20 at 10:06