I'm making a game where I want the character only to be able to shoot every 0.4 seconds or so. Currently, the character can spam bullets and it looks like a long strip of bullets coming out of the character. How can I make the charcacter wait until the next bullet comes out.
I think this would work with pygame.time.get_clicks()
but I don't really know how.
I tried doing this but then no bullets comes out. How can I make it work?
def fire():
last = pygame.time.get_ticks()
cooldown = 300
for bullet in bullets:
if bullet.y < 500 and bullet.y > 0:
bullet.y -= bullet.vel
else:
bullets.pop(bullets.index(bullet))
if keys[pygame.K_SPACE]:
now = pygame.time.get_ticks()
if now - last >= cooldown:
bullets.append(projectile((man.x + man.width // 2), (man.y - 7), 7, 3, (255, 0, 0)))
Here is the entire code if anybody wants it (I made it a rectangle instead of a picture sprite so anyone could try it.
pygame.init()
win = pygame.display.set_mode((500, 500))
class player():
def __init__(self, x, y, width, height):
self.x = x
self.y = y
self.width = width
self.height = height
self.vel = 4
self.left = False
self.right = False
def draw(self, win):
pygame.draw.rect(win, (0, 200, 0), (man.x, man.y, man.height, man.width))
if self.left:
pygame.draw.rect(win, (0, 200, 0), (man.x, man.y, man.height, man.width))
elif self.right:
pygame.draw.rect(win, (0, 200, 0), (man.x, man.y, man.height, man.width))
class projectile():
def __init__(self, x, y, width, height, color):
self.x = x
self.y = y
self.width = width
self.height = height
self.color = color
self.vel = 7
def draw(self, win):
pygame.draw.rect(win, self.color, (self.x, self.y, self.height, self. width))
def move():
if keys[pygame.K_LEFT] and man.x > man.vel:
man.x -= man.vel
man.left = True
man.right = False
elif keys[pygame.K_RIGHT] and man.x < 500 - man.width - man.vel:
man.x += man.vel
man.left = False
man.right = True
def fire():
last = pygame.time.get_ticks() # remove this if you want to try it working
cooldown = 400 # remove this if you want to try it working
for bullet in bullets:
if bullet.y < 500 and bullet.y > 0:
bullet.y -= bullet.vel
else:
bullets.pop(bullets.index(bullet))
if keys[pygame.K_SPACE]:
now = pygame.time.get_ticks() # remove this if you want to try it working
if now - last >= cooldown: # remove this if you want to try it working
bullets.append(projectile((man.x + man.width // 2), (man.y - 7), 7, 3, (255, 0, 0)))
def re_draw():
win.fill((0, 0, 0))
man.draw(win)
for bullet in bullets:
bullet.draw(win)
pygame.display.update()
man = player(400, 400, 64, 64)
bullets = []
run = True
shoot_loop = 0
clock = pygame.time.Clock()
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
keys = pygame.key.get_pressed()
fire()
move()
clock.tick(60)
re_draw()
pygame.quit()
As @gregk says, the error is that you set last = pygame.time.get_ticks()
inside the fire
function, which is called each iteration of the main loop.
You are saying to the program that the time of the last shot is always the time of the last iteration, even if there was not a shot. Hence now - last >= cooldown
will never be True, since last
is always updated to the later time.
This can be solved in many ways, but the key point is how to track the flowing time. You don't have to update last
each iteration.
A close approach to your current code (to avoid to edit a lot of stuff) is the following. Edit your fire()
function this way:
def fire():
global cooldown_tracker
cooldown_tracker += clock.get_time()
if cooldown_tracker > 400:
cooldown_tracker = 0
for bullet in bullets:
if bullet.y < 500 and bullet.y > 0:
bullet.y -= bullet.vel
else:
bullets.pop(bullets.index(bullet))
if keys[pygame.K_SPACE] and cooldown_tracker == 0:
bullets.append(projectile((man.x + man.width // 2), (man.y - 7), 7, 3, (255, 0, 0)))
And add
cooldown_tracker = 0
before the main loop (just before while run
).
In this solution, rather than pygame.time.get_ticks()
I use the clock
object you already have.
I use a cooldown_tracker
variable, each iteration (when the fire()
function is called) the time of the last iteration is added to the tracker, and if this time is greater than 400 ms, the tracker is reset to 0. A bullet is added to the list (a shot) only if the tracker is 0, meaning that the cooldown time has elapsed.