Задать вопрос
@max_1O

Как сделать бесконечную стрельбу в pygame?

Здравствуйте всем. Пишу игру вроде alien invasion с помощью pygame. Не могу реализировать так чтоб когда игрок нажал и держал кнопку Space нажатым пули стрелялись бесконечно... Пробовал циклами, там все пули разом выпускается как один(проверял с помощью print(len(), пули столько, сколько я установил). Проверял с помощью time.sleep(), так вообще корабль тоже остановился и вообще не получился задумка. Погуглил, но там другие ответы на другие вопросы. Рад буду за помощь
Основной модуль
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


game_functions.py
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


settings.py
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


bullets.py
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


ship.py
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)
  • Вопрос задан
  • 636 просмотров
Подписаться 1 Простой Комментировать
Решения вопроса 1
@o5a
Проблема в том, что событие нажатия на кнопку срабатывает только в момент нажатия. Так что если просто держать пробел, то в каждом последующем цикле событие нажатия не срабатывает, но флаг fire сбрасывается в False каждый цикл, поэтому стрельба останавливается.
Можно флаг fire привязать к самому кораблю как аттрибут, т.е. в __init__
self.fire = False
И в событиях работать именно с атрибутом класса, а не передавать отдельную переменную fire.
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

Аналогично изменить в функции отпускания кнопки.
Но т.к. событие нажатия не срабатывает повторно каждый цикл, то и само создание новых пуль не будет работать в той функции, так что ее нужно перенести туда, где срабатывает каждый цикл, например в тот же check_events
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
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы