Как я могу стрелять пули с пробелом? - PullRequest
1 голос
/ 10 января 2020

Вот мой код

import pygame, os

os.environ["SDL_VIDEO_CENTERED"] = "1"
pygame.init()

win = pygame.display
d = win.set_mode((1200, 600))

class player:
    def __init__(self, x, y, height, width):
        self.x = x
        self.y = y
        self.height = height
        self.width = width
        self.speed = 2

    def draw(self):
        pygame.draw.rect(d, (0, 0, 0), (self.x, self.y, self.width, self.height))

    def move_left(self):
        self.x -= self.speed

    def move_right(self):
        self.x += self.speed


class bullet:
    def __init__(self):
        self.radius = 10
        self.speed = 20


    def shoot(self):
        x = p.x
        y = p.y
        self.shooting = True
        while self.shooting:
            d.fill((98, 98, 98))
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    pygame.quit()
                    quit()

            y -= self.speed
            pygame.draw.circle(d, (255, 0, 0), (x, y), self.radius)
            pygame.time.Clock().tick(100)
            win.update()

            if y <= 0:
                self.shooting = False


b = bullet()
p = player(600, 500, 50, 30) 
while True:
    d.fill((98, 98, 98))
    p.draw()
    for event in pygame.event.get():
        pass

    if event.type ==  pygame.KEYDOWN:
        if event.key == pygame.K_SPACE:
            b.shoot()
        if event.key == pygame.K_LEFT:
            p.move_left()
        if event.key == pygame.K_RIGHT:
            p.move_right()



    win.update()

Это то, что я мог бы придумать после нескольких проб и ошибок, но это действительно неэффективно. Во-первых, игрок разочаровывается, когда я нажимаю пробел. Я думаю, это очевидно, поскольку у меня есть разные петли для стрельбы и игрока, но я не знаю, как обойти это и реализовать и стрельбу, и игрока в одном и том же l oop. Вторая проблема, которую я имею, ломает while self.shooting: l oop. Я попытался сломать его, когда у достигнет определенной точки, сделав это

 if y <= 0:
     self.shooting = False

, но этот настоящий разрыв. Вместо этого он снова запускает l oop. Еще одна странная проблема, с которой я сталкиваюсь, заключается в том, что каждый раз, когда я двигаю мышь (слегка быстро) или нажимаю сразу несколько кнопок, это ломает while self.shooting l oop.

1 Ответ

1 голос
/ 11 января 2020

Обратите внимание, что имена классов обычно должны использовать соглашение CapWords. (См. Руководство по стилю для Python Код - Имена классов )
Это означает, что оно должно быть Player и Bullet, а не player и bullet

У вас есть приложение l oop, так что используйте его. Все объекты постоянно обновляются и отрисовываются в основном приложении l oop, в каждом кадре.

Класс Bullet не нуждается ни в каком l oop. Конструктор должен иметь параметры для позиции (x, y). Далее он нуждается в методе, который изменяет позицию и метод, который использует aws пуля:

class Bullet:
    def __init__(self, x, y):
        self.radius = 10
        self.speed = 10
        self.x = x
        self.y = y

    def update(self):
        self.y -= self.speed#

    def draw(self):
        pygame.draw.circle(d, (255, 0, 0), (self.x, self.y), self.radius)

Используйте список bullets. Создайте новый маркер при нажатии пробел . Переместите пули (update) в каждом кадре на remove пули, если они находятся вне окна. Нарисуйте оставшиеся маркеры в каждом кадре:

bullets = []

# [...]
while run:

    for event in pygame.event.get():
        # [...]
        if event.type ==  pygame.KEYDOWN:
            if event.key == pygame.K_SPACE:
                bullets.append(Bullet(p.x+p.width//2, p.y))

    # [...]
    for b in bullets:
        b.update()
        if b.y < 0:
            bullets.remove(b)

    # [...]
    for b in bullets:
        b.draw()

Далее используйте pygame.key.get_pressed(), чтобы узнать состояние клавиш в каждом кадре и обновить положение игрока:

while run:

    # [...]

    keys = pygame.key.get_pressed()
    if keys[pygame.K_LEFT]:
        p.move_left()
    if keys[pygame.K_RIGHT]:
        p.move_right()

Полный пример:

import pygame, os

os.environ["SDL_VIDEO_CENTERED"] = "1"
pygame.init()

win = pygame.display
d = win.set_mode((1200, 600))
clock = pygame.time.Clock()

class Player:
    def __init__(self, x, y, height, width):
        self.x = x
        self.y = y
        self.height = height
        self.width = width
        self.speed = 2

    def draw(self):
        pygame.draw.rect(d, (0, 0, 0), (self.x, self.y, self.width, self.height))

    def move_left(self):
        self.x -= self.speed

    def move_right(self):
        self.x += self.speed


class Bullet:
    def __init__(self, x, y):
        self.radius = 10
        self.speed = 10
        self.x = x
        self.y = y

    def update(self):
        self.y -= self.speed#

    def draw(self):
        pygame.draw.circle(d, (255, 0, 0), (self.x, self.y), self.radius)


bullets = []
p = Player(600, 500, 50, 30) 

run = True
while run:
    clock.tick(100)

    # handel events
    for event in pygame.event.get():
        if event.type ==  pygame.QUIT:
            run = False
        if event.type ==  pygame.KEYDOWN:
            if event.key == pygame.K_SPACE:
                bullets.append(Bullet(p.x+p.width//2, p.y))

    # update objects
    keys = pygame.key.get_pressed()        
    if keys[pygame.K_LEFT]:
        p.move_left()
    if keys[pygame.K_RIGHT]:
        p.move_right()
    for b in bullets:
        b.update()
        if b.y < 0:
            bullets.remove(b)

    # clear display
    d.fill((98, 98, 98))

    # draw scene
    for b in bullets:
        b.draw()
    p.draw()

    # update display
    win.update()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...