До сих пор мы с
вами выполняли рисование в клиентской области окна, используя переменную sc:
import pygame
pygame.init()
W = 600
H = 400
sc = pygame.display.set_mode((W, H))
pygame.display.set_caption("Класс Surface")
pygame.display.set_icon(pygame.image.load("app.bmp"))
WHITE = (255, 255, 255)
BLUE = (0, 0, 255)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
FPS = 60 # число кадров в секунду
clock = pygame.time.Clock()
while 1:
for event in pygame.event.get():
if event.type == pygame.QUIT:
exit()
clock.tick(FPS)
Эта переменная
ссылается на класс Surface, который связан с окном всего
приложения. Однако, при необходимости, мы можем создать дополнительные
поверхности рисования, используя конструктор класса Surface, например, так:
surf = pygame.Surface((200, 200))
surf.fill(RED)
sc.blit(surf, (50, 50))
pygame.display.update()
В результате на
поверхности sc будет отображена
еще одна поверхность surf со всем своим содержимым:
Спрашивается:
зачем создавать дополнительный объект surf, когда можно
все рисовать непосредственно на основной поверхности sc? Это сделано главным
образом для удобства: мы можем на дополнительной поверхности нарисовать сложную
графическую информацию, а затем, переносить ее в область главного окна, просто,
используя операцию:
sc.blit(surf, (x, y))
Здесь x, y – координаты
верхнего левого угла, от которого позиционируется вторая поверхность surf. Затем,
достаточно менять в цикле координаты x, y для создания
простой анимации нашего графического образа. Перерисовывать каждый раз сложную
графическую информацию уже не придется. В этом основное достоинство таких
поверхностей.
Класс Surface имеет множество
полезных методов. Подробно все их можно посмотреть на странице официальной
документации:
https://www.pygame.org/docs/ref/surface.html
Один из них мы
уже использовали – это метод:
Surface.blit(source, pos, …)
который
отображает содержимое поверхности source на поверхности Surface. Другой весьма
полезный метод:
Surface.set_alpha(alpha)
задает степень
прозрачности поверхности:
-
alpha = 0 – полностью
прозрачная;
-
alpha = 255 – полностью
непрозрачная;
Например, можно
сделать так:
surf = pygame.Surface((200, 200))
surf.fill(RED)
pygame.draw.circle(surf, GREEN, (100, 100), 80)
surf_alpha = pygame.Surface((W, 100))
pygame.draw.rect(surf_alpha, BLUE, (0, 0, W, 100))
surf_alpha.set_alpha(128)
surf.blit(surf_alpha, (0, 50))
sc.blit(surf, (50, 50))
pygame.display.update()
Мы здесь
определяем две дополнительные поверхности: surf и surf_alpha. Причем, surf_alpha полупрозрачная
и располагается на surf. В итоге, имеем такую иерархию поверхностей:
И обратите
внимание на такой эффект: поверхность surf_alpha по ширине
больше, чем surf. Но, так как surf является
родителем для surf_alpha, то все, что
выходит за пределы surf – обрезается. В результате, мы видим следующее
отображение:
Вот так можно
создавать иерархию объектов Surface в PyGame. Причем, если
поменять порядок следования слоев:
surf_alpha.blit(surf, (0, 0))
sc.blit(surf_alpha, (50, 50))
То поверхность surf
также будет отображаться как полупрозрачная – она унаследует это свойство от
родителя surf_alpha:
В заключение
этого занятия я приведу небольшую программу простой анимации поверхностей
(слоев):
import pygame
pygame.init()
W = 600
H = 400
sc = pygame.display.set_mode((W, H))
pygame.display.set_caption("Класс Surface")
pygame.display.set_icon(pygame.image.load("app.bmp"))
WHITE = (255, 255, 255)
BLUE = (0, 0, 255)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
FPS = 60 # число кадров в секунду
clock = pygame.time.Clock()
surf = pygame.Surface((W, 200))
bita = pygame.Surface((50, 10))
surf.fill(BLUE)
bita.fill(RED)
bx, by = 0, 150
x, y = 0, 0
while 1:
for event in pygame.event.get():
if event.type == pygame.QUIT:
exit()
surf.fill(BLUE)
surf.blit(bita, (bx, by))
if bx < W:
bx += 5
else:
bx = 0
if y < H:
y += 1
else:
y = 0
sc.fill(WHITE)
sc.blit(surf, (x, y))
pygame.display.update()
clock.tick(FPS)
Здесь создается
два слоя: surf и bita, причем bita рисуется на surf, а surf уже на основной
поверхности sc. Далее, в цикле
слой surf смещается вниз
на 1 пиксель за итерацию, а слой bita на 5 пикселей по
горизонтали. После запуска программы мы видим, что слой bita смещается
относительно surf, а слой surf движется
относительно основного слоя sc. Этот простой пример показывает как
можно создавать более сложную анимацию с использованием поверхностей.