kepsk1y
kepsk1y

Reputation: 25

Remove a bullet from the game after going off-screen

I have to create Space Invaders for my programming course in college which would be fine, but I have a problem with removing a bullet from the game after going off-screen. In the game, the bullets move to the right and should disappear after leaving the screen, but I do not know how to create it.

It's a module of bullet structure

import pygame
from pygame.sprite import Sprite

class Bullet(Sprite):
    def __init__(self, ai_settings, screen, ship):
        #Creates a bullet object in the current position of the ship
        super(Bullet, self).__init__()
        self.screen = screen

        #Create bullets in position(0,0) and set correct position
        self.rect = pygame.Rect(0, 0
            , ai_settings.bullet_widht, ai_settings.bullet_height)
        self.rect.centery = ship.rect.centery
        self.rect.right = ship.rect.right

        #Position of bullets kept in float format
        self.x = float(self.rect.x)

        self.color = ai_settings.bullet_color
        self.speed_factor = ai_settings.bullet_speed_factor

    def update(self):
        #Moves the bullet right the screen
        #Update a position of bullet in float format
        self.x += self.speed_factor
        #Update a position of rectangle
        self.rect.x = self.x

    def draw_bullet(self):
        #Displaying a bullet on the screen
        pygame.draw.rect(self.screen, self.color, self.rect)

It's a game function module

import sys
import pygame
from bullet import Bullet

def check_keydown_events(event, ai_settings, screen, ship, bullets):
    #Reacts to keystrokes
    if event.key == pygame.K_RIGHT:
        ship.moving_right = True
    elif event.key == pygame.K_LEFT:
        ship.moving_left = True
    elif event.key == pygame.K_UP:
        ship.moving_up = True
    elif event.key == pygame.K_DOWN:
        ship.moving_down = True
    elif event.key == pygame.K_SPACE:
        fire_bullets(ai_settings, screen, ship, bullets)

def check_keyup_events(event, ship):
    #Reacts when keys are released
    if event.key == pygame.K_RIGHT:
        ship.moving_right = False
    elif event.key == pygame.K_LEFT:
        ship.moving_left = False    
    elif event.key == pygame.K_UP:
        ship.moving_up = False
    elif event.key == pygame.K_DOWN:
        ship.moving_down = False

def check_events(ai_settings, screen, ship, bullets):
    #Handles keystrokes and mouse events
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
        elif event.type == pygame.KEYDOWN:
            check_keydown_events(event, ai_settings, screen, ship, bullets)
        elif event.type == pygame.KEYUP:
            check_keyup_events(event, ship)

def update_screen(ai_settings, screen, ship, bullets):
    #Updates the screen, and the last picture
    screen.fill(ai_settings.bg_color)
    #All bulets Displays behind ship and aliens
    for bullet in bullets.sprites():
        bullet.draw_bullet()
    ship.blitme()
    #Displays the last screen
    pygame.display.flip()

def update_bullets(bullets):
    #Delete bullets, over the edge of the screen
    for bullet in bullets.copy():
        if bullet.rect.bottom <= 0:
            bullets.remove(bullet)

def fire_bullets(ai_settings, screen, ship, bullets):
    #Create a new bullet and add it to the group bullets
    if len(bullets) < ai_settings.bullets_allowed:
        new_bullet = Bullet(ai_settings, screen, ship)
        bullets.add(new_bullet)

Upvotes: 1

Views: 422

Answers (1)

import random
import random

Reputation: 3245

I think you're using a pygame.sprite.Group to keep track of your bullets, but you can use it in a more elegant way. Each Bullet sprite is redrawing every game loop, you should create an image attribute for Bullet on sprite creation, then call bullets.draw() to draw all the bullets. Your update function is fine for the bullet movement, but you can add the bounds check and kill the sprite if it is off the screen.

Then in your main game loop, you can just call bullets.update() to move the bullets, and bullets.draw() to draw the bullets.

I've created a minimal example to show what I mean, based on your code. Bullets are created on a key press and removed once they're off the screen.

import random
import pygame

WIDTH, HEIGHT = 640, 480
FPS = 60

class Bullet(pygame.sprite.Sprite):
    def __init__(self, bullet_width=10, bullet_height=3):
        # Creates a bullet object in the current position of the ship
        super(Bullet, self).__init__()
        # Create a image for the bullet
        self.image = pygame.Surface((bullet_width, bullet_height))
        self.image.fill(pygame.Color("gold"))
        self.rect = self.image.get_rect()
        # set the bullet position to the left of the screen and a random y
        self.rect.x = 0
        self.rect.y = random.randint(0, HEIGHT - bullet_height)
        self.speed_factor = 3

    def update(self):
        # Moves the bullet right the screen
        self.rect.x += self.speed_factor
        # remove the sprite from the group if it is off the screen
        if self.rect.x > WIDTH:
            self.kill()

pygame.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
clock = pygame.time.Clock()
bullets = pygame.sprite.Group()

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.KEYDOWN:
            # spawn a bullet
            bullets.add(Bullet())
    # update game state
    bullets.update()
    # draw the background
    screen.fill(pygame.Color("turquoise"))
    # draw bullets
    bullets.draw(screen)
    # update display
    pygame.display.update()
    # update window title to display the number of bullets
    pygame.display.set_caption(f"Bullets: {len(bullets.sprites())}")
    clock.tick(FPS)
pygame.quit()

Screenshot

Upvotes: 1

Related Questions