Как правильно наследовать класс Surface в Pygame - PullRequest
1 голос
/ 25 октября 2019

Чтобы применить ООП на практике, я создал свой собственный класс Window, который наследуется от pygame.Surface, и добавляет функциональность. Согласно источнику , следующему за , это то, что я должен сделать:

class MyWindow(pygame.Surface):
    def __init__(self, w, h):
        pygame.Surface.__init__(self, size=(w, h))
        self.screens: list[Screen] = []  # For example

Я пробовал следующий код, и он, кажется, работает нормально, до точки, где display.update()называется. Это выдает pygame.error.

myWin: MyWindow = MyWindow(200, 200)
print(myWin)    # This correctly prints: <Surface(200x200x32 SW)>

pygame.draw.rect(myWin, (255, 255, 255), (90, 90, 20, 20))
pygame.display.update()
pygame.time.delay(1000)

Этот код даже не создает фактическое окно. Напротив, следующий код работает просто отлично, вместо этого полагаясь на функцию display.set_mode() для инициализации Surface.

pyWin: pygame.Surface = pygame.display.set_mode((200, 200))
pygame.draw.rect(pyWin, (255, 255, 255), (90, 90, 20, 20))
pygame.display.update()  # Actually shows the square
pygame.time.delay(1000)

The desired output

Ясно display.set_mode() делает то, что Surface.__init__() не делает.

TL; DR: Как я могу инициализировать объект, наследуемый от Surface, таким образом, чтобы он действительно отображал и обновлял окно?

Спасибо!

1 Ответ

1 голос
/ 25 октября 2019

TL; DR: Как я могу инициализировать объект, унаследованный от Surface, таким образом, чтобы он фактически отображал и обновлял окно?

Я бы сказал, что вы не можетеделайте это так, как вы думаете, и есть веская причина, по которой вы никогда не захотите это делать.
Нужно помнить пару вещей:

  1. A Surface - это просто2D массив пикселей с удобными методами для чтения / редактирования / записи значений этих пикселей. Напиши где? Для других поверхностей. Вы можете иметь столько поверхностей, сколько хотите в игре, каждая из которых хранит изображение различных элементов игры (вашего главного героя, врага, элемента карты и т. Д.). Вы можете написать содержимое Поверхности поверх другой Поверхности, чтобы создавать сложные изображения.
    A Surface само по себе не имеет связи с экраном (то есть с тем, что показано в окне, которое вы видите на вашемМонитор ПК).
  2. display - это особый Surface, экземпляр которого pygame.display.set_mode(). Это Surface, как и все остальные, которые вы можете создать с помощью класса Surface, но это, и только эта поверхность, представляет дисплей, то есть то, что вы видите на мониторе.

Этоозначает, что pygame.Surface экземпляр никогда не отображается на экране. Чтобы показать материалы на экране, вам нужно перетянуть другие Поверхности (т.е. скопировать их содержимое) куда-нибудь на специальную display Поверхность.

Теперь давайте вернемся к вашему вопросу. С учетом того, что я только что объяснил, вы могли бы спросить: Тогда я могу написать Surface подкласс, такой, что каждый раз, когда значение Surface изменяется, оно автоматически сбрасывается на display и display.update() вызывается`?

Ну, это будет сложно. Если вы используете функцию из pygame.draw, то Surface является аргументом, поэтому вам понадобится хороший прием, чтобы аргумент понял, когда он используется.
Однако, поверьте мне: вы не хотите этого делать. Как только ваша игра станет немного сложнее, она станет крайне неэффективной. Причина в том, что для копирования и рисования требуется время, поэтому вы хотите оптимизировать эти операции, выполняя их только при необходимости. Если в вашей игре много поверхностей, вы хотите перетаскивать их на display на каждой итерации вашего основного цикла (или на каждый кадр, если хотите), чтобы «подготовить» новый кадр, и вызывать display.update только один раз.

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