Bruno Moreno
Bruno Moreno

Reputation: 33

Pygame: my bullet class does nothing apart from being drawn

So im trying to make a local multiplayer game, i have created the player class which works fine so far.

Now im trying to do a bullet class to create different types of shots for the player's spaceships, however upon calling my bullet, it only gets drawn to the screen where the player was at the start of the game and it doesnt move (so far just trying to program it to move)

Here is the code:

import pygame

pygame.init()

#Display screen
screen = pygame.display.set_mode((800, 600))

pygame.display.set_caption("Space Arena")

background = pygame.image.load(r'C:\Users\Bruno\Documents\PythonProjects\Pygame\Multiplayer\Images\background.png').convert_alpha()

playerImg = pygame.image.load(r'C:\Users\Bruno\Documents\PythonProjects\Pygame\Multiplayer\Images\Player.png').convert_alpha()
player2Img = pygame.image.load(r'C:\Users\Bruno\Documents\PythonProjects\Pygame\Multiplayer\Images\Player2.png').convert_alpha()
regular_bullet = pygame.image.load(r'C:\Users\Bruno\Documents\PythonProjects\Pygame\Multiplayer\Images\bullet.png').convert_alpha()


class Player:
    def __init__(self, image, x, y, isPlayer1, isPlayer2):
        self.image = image
        self.x = x
        self.y = y
        self.isPlayer1 = isPlayer1
        self.isPlayer2 = isPlayer2

    def Move(self):
        key_states = pygame.key.get_pressed()
        x_change = 0.2
        y_change = 0.2

        if self.isPlayer1:
            if key_states[pygame.K_a]:
                self.x += -x_change
            if key_states[pygame.K_d]:
                self.x += x_change
            if key_states[pygame.K_w]:
                self.y += -y_change
            if key_states[pygame.K_s]:
                self.y += y_change
        elif self.isPlayer2:
            if key_states[pygame.K_LEFT]:
                self.x += -x_change
            if key_states[pygame.K_RIGHT]:
                self.x += x_change
            if key_states[pygame.K_UP]:
                self.y += -y_change
            if key_states[pygame.K_DOWN]:
                self.y += y_change

    def draw(self, screen):
        screen.blit(self.image,(self.x,self.y))


    def ColorPlayer(self ,image):
        if self.isPlayer1:
            self.image.fill((190,0,0,100), special_flags = pygame.BLEND_ADD)
        if self.isPlayer2:
            self.image.fill((0,0,190,100), special_flags = pygame.BLEND_ADD)

class Bullet():
    def __init__(self, image, bulletx, bullety):
        self.image = image
        self.bulletx = bulletx
        self.bullety = bullety
        self.bullet_state = "ready"

    def draw(self, screen):
        if self.bullet_state == "fire":
            screen.blit(self.image,(self.bulletx,self.bullety))

    def shoot(self):
        change_x = 0.9
        if self.bullet_state == "fire":
            self.bulletx += change_x
        if self.bulletx > 800:
            self.bullet_state = "ready"



def redrawWindow(screen, player, player2, background, player_bullet):
    screen.fill((255,255,255))
    screen.blit(background,(0,0))
    player.draw(screen)
    player2.draw(screen)
    player_bullet.draw(screen)
    pygame.display.update()

def Main():
    done = False

    player = Player(playerImg,200,200,True,False)

    player2 = Player(player2Img,600,200,False,True)

    player1_bullet = Bullet(regular_bullet, player.x, player.y)

    while not done:

        player.Move()
        player2.Move()
        player.ColorPlayer(playerImg)
        player2.ColorPlayer(player2Img)

        redrawWindow(screen, player, player2, background, player1_bullet)

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                done = True

            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_SPACE:
                    if player1_bullet.bullet_state is "ready":
                        player1_bullet.bullet_state = "fire"
                        player1_bullet.shoot()


Main()

Upvotes: 1

Views: 101

Answers (3)

Rabbid76
Rabbid76

Reputation: 211116

You have to change 2 things.

The method Bullet.shoot() has to be continuously invoked in the main application loop. Note, this method updates the bullet dependent on its state. If the state of the bullet is "fire" then the bullet moves. Else it stands still.

Update the position of the bullet when it is fired. The bullet always has to start at the position of the player:

def Main():
    # [...]

    while not done:
        # [...]

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                done = True

            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_SPACE:

                    if player1_bullet.bullet_state is "ready":
                        player1_bullet.bullet_state = "fire"
                        player1_bullet.bulletx = player.x
                        player1_bullet.bullety = player.y

        player1_bullet.shoot()

Upvotes: 0

Glenn Mackintosh
Glenn Mackintosh

Reputation: 2779

The only code you have that changes the bullet position is this bit inside the shoot method.

def shoot(self):
    change_x = 0.9
    if self.bullet_state == "fire":
        self.bulletx += change_x

Nothing else moves it. You need to have a move function that adjusts it position and call that each frame. In fact your shoot function is a bit odd it looks more like what the move function would look like. Perhaps rename it to move() and call it each frame?

That function is a bit unusual for a shoot() function, since it moves an existing bullet instead of firing a new one. Normally a shoot method would be expected to be a method in the player and to create a new bullet. It does not really make sense for a bullet instance function to shoot and to create a new bullet. Also you seem to have coded it so that there is a single bullet that goes to 800 and then can be re-fired, but you do not have anything that resets the bullets position back to where the player is.

It might make more sense for the 'ready' and 'fire' state to be a state of the player since the player is the one that can or cannot fire. Also the shoot() method is more commonly in the player class and when it fires (the player is in state 'ready') it creates a new Bullet instance at the players position.

The bullet move() method would be called each frame just like the player move() functions are. Normally there would be more than one bullet allowed at a time and so you would keep a list of the and have to iterate through the list of bullets moving them along (and doing collision checking to see if they hit anything). If a bullet goes off the screen or hits something then you remove the bullet from the bullet list.

Upvotes: 0

mzulch
mzulch

Reputation: 1539

It looks like shoot is effectively the "update" function for your bullet, and the code inside would need to be called every frame (like with player.Move()) for the bullet to keep moving after it's fired.

Upvotes: 0

Related Questions