Классы и экземпляры обновления - PullRequest
1 голос
/ 08 июля 2020

Я впервые пытаюсь использовать классы в своей программе, но у меня возникают проблемы с обновлением атрибутов моего класса.

Я использовал библиотеку pygame в python для это, и я пытаюсь использовать классы, чтобы стрелять лазером от одной точки экрана вверх. Однако лазер остается на своем месте и совсем не успевает подняться на go. Я не знаю, что делать.

Размер окна: 800 x 600

class Mechanics(Display):

    def __init__(self):
        super().__init__()
        self.laserX_change = 0
        self.laserY_change = 10
        self.userX_change = 0
        self.userX = 360
        self.laserX = 0
        self.laserY = 480
        self.laser_position = 'active'
        self.laserImg = pygame.image.load('laser.png')

   def fireLaser(self):

        self.laserY -= self.laserY_change

        if self.laserY <= 0:
            self.laserY = 480
            self.laser_position = 'active'

   def activateLaser(self):

        screen.blit(self.laserImg, (self.laserX + 16, self.laserY + 10))
        self.fireLaser()

вот где вы используете пробел, чтобы использовать звуковой эффект и сделать его go по той же траектории при движении пользователя

класс Бег (Механика):

def __init__(self):
    Mechanics.__init__(self)



def run(self):

    if event.key == pygame.K_SPACE:
        if self.laser_position == 'active':
            self.laserX = self.userX
            laserSound = mixer.Sound('shoot.wav')
            laserSound.play()
            self.activateLaser()
            
             

1 Ответ

0 голосов
/ 09 июля 2020

Я думаю, вам нужно понимать между «определением» класса и «Экземпляром» класса. Скажем, я определяю класс для хранения информации о цвете:

class Colour:
    def __init__( self, r, g, b, a=0 ):
        self.red   = r
        self.green = g
        self.blue  = b
        self.alpha = a

Вот и все, определение. Обычно не пишут Colour.red = 33, поскольку это определение цвета, а не его экземпляр. Подумайте об определении как о планах для пустого упаковочного контейнера. Вы должны создать его, прежде чем сможете начать изменять его содержание. Итак, мы делаем единицу:

purple = Colour( 24, 64, 319 )

Итак, теперь purple является «экземпляром» Colour. Мы можем изменить фиолетовый цвет:

# make purple darker
purple.red   -= 20
purple.green -= 20
purple.blue  -= 20

Это то, что вам нужно сделать с вашим классом Mechanics (Laser), создать его экземпляр, а затем изменить. Но сначала я хотел бы немного подправить класс:

class Laser():
    def __init__( self, x, y=480, x_change=0, y_change=10 ):
        self.laserX = x
        self.laserY = y
        self.laserX_change = x_change
        self.laserY_change = y_change
        self.image = pygame.image.load('laser.png').convert_alpha()
        self.rect  = self.image.get_rect()
        self.rect.center = ( x, y )
        self.sound = mixer.Sound('shoot.wav')

    def soundEffect( self ):
        self.sound.play()  # pew! pew!

    def draw( self, window ):
        window.blit( self.image, self.rect )

    def update( self ):
        self.laserX += self.laserX_change
        self.laserY += self.laserY_change
        self.rect.move_ip( self.laserX_change, self.laserY_change )

Это позволяет нам создать Laser с заданными координатами (x, y). Этот макет класса действительно удобен для создания игровых элементов, таких как lasers / bullets / et c. потому что при активации код может просто создать новый экземпляр класса в координатах игрока:

def run(self):
    if event.key == pygame.K_SPACE:
        if self.laser_position == None:
            self.laser_position = Laser( self.userX )
            self.laser_position.soundEffect()
            # when laser hits, goes off-screen, etc. 
            # self self.laser_position back to None

Обратите внимание, что я никогда напрямую не настраивал переменные-члены класса извне класса . Это нормальный способ для языков, отличных от Python, и в противном случае это не одобрилось бы (и сделало бы плохой анализ кода), но в Python это как-то более приемлемо. Тем не менее: не делайте этого.

ЧТО! Зачем!? Вернемся к цветному примеру. Наивный пользователь класса цвета может сделать что-то вроде:

# make a REALLY DARK purple
purple.red   -= 200
purple.green -= 200
purple.blue  -= 200

Дать нам фиолетовый цвет с компонентом .red из -176 (24-200), который не является допустимым цветом. Лучше иметь функцию в классе, который это обрабатывал, потому что это эксперт по собственному внутреннему состоянию:

class Colour:
    #...
    def makeDarker( self, delta ):
        self.red   = min( 0, self.red   - delta )
        self.green = min( 0, self.green - delta )
        self.blue  = min( 0, self.blue  - delta )

В других языках внутренние переменные-члены часто устанавливаются как «частные», поэтому невозможно получить доступ напрямую. Но это еще один ответ.

Последнее замечание: в приведенном выше коде я отразил то, что было в вопросе, но также добавил PyGame Rect в ваш класс. PyGame Rects великолепны , потому что включают в себя координаты, а также размеры вашего лазерного изображения. Их можно легко использовать как с столкновениями, * с , так и с рисованием. Таким образом, вам не нужно поддерживать отдельные X и Y для ваших объектов, просто сохраните все это внутри Rect.

class Laser:
    # ...
    def hitPlayer( self, player_rect ):
        is_overlapping = self.rect.colliderect( player_rect )
        return is_overlapping
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...