Пуль на экране может быть сразу много. Заводить переменную под каждую —
невозможно. Поэтому держим их в списке bullets. С ним всего
три действия:
BULLET_W, BULLET_H = 4, 14 BULLET_SPEED = 9 bullets = [] # СПИСОК пуль — пока пустой while True: for event in pygame.event.get(): # ... выход ... if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE: # выстрел — ДОБАВЛЯЕМ новую пулю в список bullets.append(pygame.Rect(ship_x - BULLET_W // 2, ship_y, BULLET_W, BULLET_H)) # ... движение корабля ... # каждая пуля летит вверх; улетевшую за экран УБИРАЕМ из списка for b in bullets[:]: # bullets[:] — копия, чтобы безопасно удалять b.y -= BULLET_SPEED if b.bottom < 0: bullets.remove(b) screen.fill(BG) for b in bullets: # рисуем каждую пулю из списка pygame.draw.rect(screen, BULLET_COLOR, b)
KEYDOWN, а не get_pressed()?Движение мы проверяем через get_pressed() — оно «истинно» каждый
кадр, пока держишь клавишу. Для выстрела так нельзя: иначе одно нажатие
пробела даст десятки пуль за секунду. KEYDOWN срабатывает
один раз на каждое нажатие — один пробел, одна пуля.
bullets[:]?Это копия списка. Нельзя удалять из списка и одновременно бежать по
нему — Python запутается и пропустит элементы. Поэтому идём по копии
bullets[:], а удаляем из настоящего bullets. В Змейке
мы список не трогали во время цикла — здесь трогаем, поэтому и копия.
RectКак и кирпичи в Арканоиде, пуля — это pygame.Rect(x, y, ширина, высота).
У прямоугольника удобно двигать b.y и проверять край через
b.bottom. А ещё потом он сам умеет проверять столкновения.
BULLET_SPEED = 14.BULLET_W = 8.ship_x - 12 и ship_x + 12.