Menu
CoddyTech

Hold to Fire

Part of the Sprites and Images section of Coddy's Pygame journey. Lesson 31 of 36.

Pressing Space for every shot tires the fingers. Most shooters fire while the button is held, but a laser every frame would be a solid beam. A cooldown limits the rate: after a shot, the next waits 250 milliseconds.

Remember when the last shot was, and fire only when Space is held and enough time has passed:

keys = pygame.key.get_pressed()
now = pygame.time.get_ticks()
if keys[pygame.K_SPACE] and now - last_shot >= 250:
    lasers.add(Laser(player.rect.centerx, player.rect.top))
    last_shot = now

now - last_shot is how long ago the last shot was. Make last_shot = 0 before the loop. Holding Space now fires four lasers a second, and tapping it fast fires no faster than that.

This replaces the KEYDOWN firing: one way to fire, with one rule.

challenge icon

Challenge

Medium
  1. Remove the KEYDOWN firing from the event loop.
  2. Make last_shot = 0 before the loop.
  3. In the update part, while Space is held and at least 250 ms have passed since last_shot, fire a laser and set last_shot to now.

Try it yourself

import pygame

pygame.init()
screen = pygame.display.set_mode((640, 480))
pygame.display.set_caption("Star Patrol")
clock = pygame.time.Clock()

ship_image = pygame.image.load("assets/images/ship.png").convert_alpha()
laser_image = pygame.image.load("assets/images/laser.png").convert_alpha()


class Player(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.image = ship_image
        self.rect = self.image.get_rect(midbottom=(320, 470))

    def update(self):
        keys = pygame.key.get_pressed()
        if keys[pygame.K_LEFT]:
            self.rect.x -= 6
        if keys[pygame.K_RIGHT]:
            self.rect.x += 6
        self.rect.clamp_ip(screen.get_rect())


class Laser(pygame.sprite.Sprite):
    def __init__(self, x, y):
        super().__init__()
        self.image = laser_image
        self.rect = self.image.get_rect(midbottom=(x, y))

    def update(self):
        self.rect.y -= 10
        if self.rect.bottom < 0:
            self.kill()


player = Player()
lasers = 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 and event.key == pygame.K_SPACE:
            lasers.add(Laser(player.rect.centerx, player.rect.top))

    player.update()
    lasers.update()

    screen.fill((12, 14, 30))
    lasers.draw(screen)
    screen.blit(player.image, player.rect)
    pygame.display.flip()
    clock.tick(60)

pygame.quit()

All lessons in Sprites and Images

Practice on your own: Pygame playground