Search code examples
pythonpygame

Shoot bullet from player


So I wanted to add a shoot option to my game but at the moment when I press the spacebar, the bullet spawns in where the player is, and that's about it, it doesn't move, it just sits there, I'm new to pygame in particular so I'm not quite sure.

Please say if you need any more context than this

Heres The code:

import pygame
import random

from pygame.locals import(
    RLEACCEL,
    K_UP,
    K_DOWN,
    K_LEFT,
    K_RIGHT,
    K_ESCAPE,
    K_w,
    K_a,
    K_s,
    K_d,
    K_0,
    K_9,
    K_SPACE,
    KEYDOWN,
    QUIT
)

pygame.init()
pygame.joystick.init()
pygame.mixer.init()
pygame.display.set_caption("Dodge The Missile (ALPHA 0.11)")

SCREEN_WIDTH = 1600
SCREEN_HEIGHT = 1000

class Enemy(pygame.sprite.Sprite):
    def __init__(self):
        super(Enemy, self).__init__()
        self.surf = pygame.image.load("Missiles.png").convert()
        self.surf.set_colorkey((255,255,255), RLEACCEL)
        self.rect = self.surf.get_rect(
            center=(
                random.randint(SCREEN_WIDTH + 20, SCREEN_WIDTH + 100),
                random.randint(0, SCREEN_HEIGHT),
            )
        )
        self.speed = random.randint(Enemy_SPEED_Min, Enemy_SPEED_Max)



    def update(self):
        self.rect.move_ip(-self.speed, 0)
        if self.rect.right < 0:
            self.kill()


class Player(pygame.sprite.Sprite):
    def __init__(self):
        super(Player, self).__init__()
        self.surf = pygame.image.load("Spaceship.png").convert()
        self.surf.set_colorkey((255,255,255), RLEACCEL)
        self.rect = self.surf.get_rect()
        self.layers = 1
    def update(self, pressed_keys):
            if pressed_keys[K_UP] or pressed_keys[K_w]:
                self.rect.move_ip(0, -5)
            if pressed_keys[K_DOWN] or pressed_keys[K_s]:
                self.rect.move_ip(0, 5)
            if pressed_keys[K_LEFT] or pressed_keys[K_a]:
                self.rect.move_ip(-5, 0)
            if pressed_keys[K_RIGHT] or pressed_keys[K_d]:
                self.rect.move_ip(5, 0)

            if self.rect.left < 0:
                self.rect.left = 0
            if self.rect.right > SCREEN_WIDTH:
                self.rect.right = SCREEN_WIDTH
            if self.rect.top <= 0:
                self.rect.top = 0
            if self.rect.bottom >= SCREEN_HEIGHT:
                self.rect.bottom = SCREEN_HEIGHT
    def shoot(self):
        bullet = Bullet(self.rect.centerx, self.rect.top)
        all_sprites.add(bullet)



class Cloud(pygame.sprite.Sprite):
    def __init__(self):
        super(Cloud, self).__init__()
        self.surf = pygame.image.load("Cloud.png").convert()
        self.surf.set_colorkey((255,255,255), RLEACCEL)
        self.layers = 3
        self.rect = self.surf.get_rect(
            center=(
                random.randint(SCREEN_WIDTH + 20, SCREEN_WIDTH + 100),
                random.randint(0, SCREEN_HEIGHT)
            )
        )

    def update(self):
        self.rect.move_ip(-5, 0)
        if self.rect.right < 0:
            self.kill()

class Bullet (pygame.sprite.Sprite):
    def __init__ (self, x, y):
        super (Bullet, self).__init__()
        self.surf = pygame.image.load("Bullet.png").convert()
        self.surf.set_colorkey((255,255,255), RLEACCEL)
        self.rect = self.surf.get_rect()
        self.rect.bottom = y
        self.rect.centerx = x
        self.speedx = 5
    def update(self):
        self.rect.x += self.speedx

        if self.rect.left > SCREEN_WIDTH:
            self.kill()


class AddEnemyTimer():
    def __init__(self, Generate_Enemy_Timer, Generate_Cloud_Timer):
        self.Generate_Enemy_Timer = Generate_Enemy_Timer
        self.Generate_Cloud_Timer = Generate_Cloud_Timer

class Game_Speed_Class():
    def __init__(self, Game_Speed):
        self.Game_Speed = Game_Speed

class Enemy_Speed_Class():
    def __init__(self, First_NEW_ENEMY_SPEED, Second_NEW_ENEMY_SPEED):
        self.First_NEW_ENEMY_SPEED = First_NEW_ENEMY_SPEED
        self.Second_NEW_ENEMY_SPEED = Second_NEW_ENEMY_SPEED
Enemy_SPEED = Enemy_Speed_Class(20, 50)
Enemy_SPEED_Min = Enemy_SPEED.First_NEW_ENEMY_SPEED
Enemy_SPEED_Max = Enemy_SPEED.Second_NEW_ENEMY_SPEED

count = 0
green = (0, 255, 0)
Lives = 99999999999999



Primary_Music = pygame.mixer.music.load("Game.ogg")
pygame.mixer.music.play(loops=-1)



Milestone_Delay = 50

screen = pygame.display.set_mode((SCREEN_WIDTH,SCREEN_HEIGHT)) 

First_NEW_ENEMY_Timer = 175
Second_NEW_ENEMY_Timer = 250
First_NEW_CLOUD_Timer = 300
Second_NEW_CLOUD_Timer = 600

Generate_Timer= AddEnemyTimer(random.randint(First_NEW_ENEMY_Timer, Second_NEW_ENEMY_Timer), random.randint(First_NEW_CLOUD_Timer, Second_NEW_CLOUD_Timer))
ADDENEMY = pygame.USEREVENT + 1
pygame.time.set_timer(ADDENEMY, Generate_Timer.Generate_Enemy_Timer)

More_Enemies = pygame.USEREVENT +2
pygame.time.set_timer(More_Enemies, 3000)

ADDCLOUD = pygame.USEREVENT + 3
pygame.time.set_timer(ADDCLOUD, Generate_Timer.Generate_Cloud_Timer)

New_Progress = pygame.USEREVENT + 4
pygame.time.set_timer(New_Progress, Milestone_Delay)

Game_Framerate = Game_Speed_Class(59.94)
Set_Game_Speed = pygame.USEREVENT + 5
pygame.time.set_timer(Set_Game_Speed, 10000)

player = Player()
health = 0
green = (0, 255, 0)

enemies = pygame.sprite.Group()
all_sprites = pygame.sprite.Group()
all_sprites.add(player)
clouds = pygame.sprite.Group()

clock = pygame.time.Clock()
running = True

Large_Font = 60
Medium_Font = 40
Small_Font = 20
Small_Size = pygame.font.Font("Airstrip Four.ttf", Small_Font)
Medium_Size = pygame.font.Font("Airstrip Four.ttf", Medium_Font)
Large_Size = pygame.font.Font("Airstrip Four.ttf", Large_Font)




while running:
    for event in pygame.event.get():
            if event.type == KEYDOWN:
                if event.key == K_ESCAPE:
                    running = False
                if event.key == K_SPACE:
                    player.shoot()
                if event.key == K_0:
                    pygame.mixer.music.set_volume(0)
                if event.key == K_9:
                    pygame.mixer.music.set_volume(1)
            elif event.type == QUIT:
                running = False

            elif event.type == ADDENEMY:
                new_enemy = Enemy()
                enemies.add(new_enemy)
                all_sprites.add(new_enemy)

            elif event.type == ADDCLOUD:
                new_cloud = Cloud()
                clouds.add(new_cloud)
                all_sprites.add(new_cloud)

            elif event.type == New_Progress:
                count+= 1

            elif event.type == Set_Game_Speed:
                Enemy_SPEED_Min += 10
                Enemy_SPEED_Max += 10


            elif event.type == More_Enemies:
                First_NEW_ENEMY_Timer += 50
                Second_NEW_ENEMY_Timer += 50
                First_NEW_CLOUD_Timer += 50
                Second_NEW_CLOUD_Timer += 50


    if Lives == 0:
        running = False


    screen.fill((135,206,250))
    for entity in all_sprites:
        screen.blit(entity.surf, entity.rect)
    if pygame.sprite.spritecollide(player, enemies, True):
        print("Hit!")
        Lives -= 1



    screen.blit(Medium_Size.render(str(count), True, (0, 0, 0)), (SCREEN_WIDTH // 2, 48))
    screen.blit(Medium_Size.render(("Lives: ") + str(Lives), True, (0,0,0)), (20, 40))

    fps = str(int(clock.get_fps()))
    screen.blit(Small_Size.render(("FPS: ") + str(fps), True, (0,0,0)), (10, 0))



    pressed_keys = pygame.key.get_pressed()
    player.update(pressed_keys)
    enemies.update()
    clouds.update()
    pygame.display.flip()

    clock.tick(62)

Solution

  • Create a pygame.sprite.Group for the bullets:

    bullets = pygame.sprite.Group()
    

    Add the bullets to the group:

    class Player(pygame.sprite.Sprite):
        # [...]
    
        def shoot(self):
            bullet = Bullet(self.rect.centerx, self.rect.top)
            all_sprites.add(bullet)
            bullets.add(bullet)
    

    Update the bullets Group in the main application loop:

    while running:
        # [...]
    
        player.update(pressed_keys)
        enemies.update()
        clouds.update()
        bullets.update() # <-----
        pygame.display.flip()