Answer the question
In order to leave comments, you need to log in
How to make infinite shooting in pygame?
Hello everyone. I am writing a game like alien invasion using pygame. I can’t implement it so that when the player presses and holds the Space button pressed, the bullets shoot endlessly ... I tried it in cycles, there all the bullets are fired at once as one (I checked with print (len(), there are as many bullets as I set). I checked with time.sleep(), so in general the ship also stopped and the idea did not work out at all. I googled, but there are other answers to other questions. I will be glad for the help
Main module
import pygame
from pygame.sprite import Group
from settings import Settings
# module controlling ship,bullet,alien speed,
# amount of aliens, bullets etc.
import game_functions as gf
# module controlling changes coords of things in screen in every loop
from ship import Ship
# module of class Ship
def run_game():
pygame.init()
settings = Settings()
screen = pygame.display.set_mode((0, 0), pygame.FULLSCREEN)
ship = Ship(screen, settings) # creating ship
bullets = Group() # creating tuple to store bullets
while True:
screen.fill(settings.bg_color) # changing background color
ship.blitme() # drawing ship onto screen
gf.check_events(ship, settings, screen, bullets) # keyboard events
ship.update() # changing position of ship when player presses definite key
gf.update_screen(bullets) # changing coords of bullet after it's been fired
pygame.display.flip() # loop
run_game() # starts game
import sys
import time
import pygame
from bullet import Bullet # class of Bullet
def check_keydown_events(event, ship, settings, screen, bullets, fire):
if event.key == pygame.K_LEFT:
# left arrow keydown events
ship.move_left = True # moves ship left when key's keeping pressed
if event.key == pygame.K_RIGHT:
# right arrow keydown events
ship.move_right = True # moves ship right when key's keeping pressed
if event.key == pygame.K_DOWN:
# down arrow keydown events
ship.move_down = True # moves ship down when key's keeping pressed
if event.key == pygame.K_UP:
# up arrow keydown events
ship.move_up = True # moves ship up when key's keeping pressed
if event.key == pygame.K_SPACE:
fire = True
# fires bullets
if fire and len(bullets) < settings.bullets_allowed:
# continues firing until amount of bullets reaches limit
new_bullet = Bullet(settings, ship, screen) # creating new bullet
bullets.add(new_bullet) # adding created bullet to Group
def check_keyup_events(event, ship, fire):
# works with keydown events
if event.key == pygame.K_LEFT:
ship.move_left = False # stops moving of ship to left
if event.key == pygame.K_RIGHT:
ship.move_right = False # stops moving of ship to right
if event.key == pygame.K_UP:
ship.move_up = False # stops moving of ship to up
if event.key == pygame.K_DOWN:
ship.move_down = False # stops moving of ship to down
if event.key == pygame.K_SPACE:
fire = False # stops firing bullets
def check_events(ship, settings, screen, bullets):
"""main event checker function"""
fire = False # it'll be true when player press space
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN:
# working on keydown events
check_keydown_events(event, ship, settings, screen, bullets, fire)
# function that checks keydown event type and works according event type
elif event.type == pygame.KEYUP:
check_keyup_events(event, ship, fire)
# function that checks keyup event type and works according event type
print(len(bullets)) # to check amount of bullets on screen
def update_screen(bullets):
"""works with bullet Group"""
for bullet in bullets.sprites():
bullet.update_bullet() # changes position of bullet in every loop
bullet.draw_bullet() # draws bullets with new coords
if bullet.rect.bottom < 0:
bullets.remove(bullet) # removes bullets reached outline of screen
import pygame
class Settings():
def __init__(self):
self.screen_width = 1200
self.screen_height = 700
self.bg_color = (15, 38, 128)
self.ship_speed_factor = 1.5
self.bullet_width = 5
self.bullet_height = 15
self.bullet_color = 245, 15, 15
self.bullets_allowed = 5
self.bullet_speed_factor = 1
import pygame
from pygame.sprite import Sprite
class Bullet(Sprite):
def __init__(self, settings, ship, screen):
super(Bullet, self).__init__()
self.settings = settings
self.ship_rect = ship.rect # rect of image of ship
self.screen = screen
self.width = settings.bullet_width
self.height = settings.bullet_height
self.color = settings.bullet_color
self.rect = pygame.Rect(0, 0, self.width, self.height) # left bullet
self.rect1 = pygame.Rect(0, 0, self.width, self.height) # right bullet
# variables below makes bullets being fired from ship wings
self.rect.x = self.ship_rect.centerx - 21
self.rect1.x = self.ship_rect.centerx + 21
self.rect.y = self.ship_rect.centery - 15
self.rect1.y = self.ship_rect.centery - 15
# variables below makes coords much more correct
self.x = float(self.rect.x)
self.y = float(self.rect.y)
self.x1 = float(self.rect1.x)
self.y1 = float(self.rect1.y)
def draw_bullet(self):
# draws bullets when being called
pygame.draw.rect(self.screen, self.color, self.rect)
pygame.draw.rect(self.screen, self.color, self.rect1)
def update_bullet(self):
# changes bullets coords in every loop
# rect can't get float number, so we use variables below and return it's integer type back at the end
self.y -= self.settings.bullet_speed_factor
self.y1 -= self.settings.bullet_speed_factor
self.rect.y = self.y
self.rect1.y = self.y1
import pygame
class Ship():
def __init__(self, screen, ai_settings):
self.screen = screen
self.settings = ai_settings
self.image = pygame.image.load("images/ship.xcf") # ship image
self.rect = self.image.get_rect() # ship rect
self.screen_rect = self.screen.get_rect()
self.rect.centerx = self.screen_rect.centerx # moving ship to center
self.rect.centery = self.screen_rect.centery # vertical center aligning
self.centerx = float(self.rect.centerx) # we'll use float to be more correct
self.centery = float(self.rect.centery)
# variables below will be "True" or "False" according keydown events in game_functions.py
self.move_right = False
self.move_left = False
self.move_up = False
self.move_down = False
def update(self):
# changes ship position according keydown events in game_function.py
if self.move_right and self.rect.right < self.screen_rect.right:
self.centerx += self.settings.ship_speed_factor
if self.move_left and self.rect.left > self.screen_rect.left:
self.centerx -= self.settings.ship_speed_factor
if self.move_up and self.rect.top > self.screen_rect.top:
self.centery -= self.settings.ship_speed_factor
if self.move_down and self.rect.bottom < self.screen_rect.bottom:
self.centery += self.settings.ship_speed_factor
self.rect.centerx = self.centerx
self.rect.centery = self.centery
def blitme(self):
# draws ship onto screen
self.screen.blit(self.image, self.rect)
Answer the question
In order to leave comments, you need to log in
The problem is that the button click event fires only when the button is clicked. So if you just hold a space, then in each subsequent cycle, the click event does not fire, but the fire flag is reset to False each cycle, so the shooting stops.
You can bind the fire flag to the ship itself as an attribute, i.e. in __init__
And in events, work with the class attribute, and not pass a separate fire variable.
self.fire = False
def check_keydown_events(event, ship, settings, screen, bullets):
if event.key == pygame.K_LEFT:
# left arrow keydown events
ship.move_left = True # moves ship left when key's keeping pressed
if event.key == pygame.K_RIGHT:
# right arrow keydown events
ship.move_right = True # moves ship right when key's keeping pressed
if event.key == pygame.K_DOWN:
# down arrow keydown events
ship.move_down = True # moves ship down when key's keeping pressed
if event.key == pygame.K_UP:
# up arrow keydown events
ship.move_up = True # moves ship up when key's keeping pressed
if event.key == pygame.K_SPACE:
ship.fire = True
def check_events(ship, settings, screen, bullets):
"""main event checker function"""
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN:
# working on keydown events
check_keydown_events(event, ship, settings, screen, bullets)
# function that checks keydown event type and works according event type
elif event.type == pygame.KEYUP:
check_keyup_events(event, ship)
# function that checks keyup event type and works according event type
print(len(bullets)) # to check amount of bullets on screen
if ship.fire and len(bullets) < settings.bullets_allowed:
# continues firing until amount of bullets reaches limit
new_bullet = Bullet(settings, ship, screen) # creating new bullet
bullets.add(new_bullet) # adding created bullet to Group
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question