Python – функциональный язык программирования, который может использоваться для реализации самых разных задач. Это не только создание инструментальных приложений, но и игр. Ранее мы рассматривали библиотеку Pygame, разбирали игровые циклы и некоторые другие аспекты процесса создания игры. Сегодня же мы разберемся в теме спрайтов. Мы поймем, что это такое, для чего они могут использоваться. Продолжаем рассматривать аспекты создания игр в Python c использованием библиотеки Pygame. Если вы – начинающий программист, это руководство вам поможет разобраться в том, что такое спрайты и как с ними работать в Pygame.
Понятие спрайта
Под спрайтом подразумевается элемент компьютерной графики, который представляет двигающийся элемент экрана. Если брать двухмерную игру, то абсолютно все на экране – это спрайты. С ними можно выполнять различные действия: анимирование, заставлять их взаимодействовать друг с другом либо передавать управление человеку, который выступает игроком.
Причем в некоторых двумерных играх спрайты такие реалистичные, что они похожи больше на 3Д. И в старые времена, когда мощности компьютеров не хватало для того, чтобы отрисовывать объемные фигуры, такие варианты спрайтов были очень популярными.
Спрайты используются сейчас и в 3Д играх. Например, чтобы задать текстуру объектов.
Чтобы загрузить или выполнять отрисовку спрайтов, используются разделы «Обновление» и «Визуализация» игрового цикла. Нетрудно понять, что если в игре большое количество спрайтов, то в этом случае цикл станет большим и запутанным. Для того, чтобы решить эту проблему, используется группировка спрайтов.
Под набором спрайтов подразумевается такая их совокупность, которая позволяет им отображаться в один момент времени.
Чтобы создать группу спрайтов, необходимо написать строки кода, подобные этим.
clock = pygame.time.Clock() all_sprites = pygame.sprite.Group()
Также этой возможностью можно воспользоваться путем добавления группы в цикл целиком.
# Обновление all_sprites.update() # Отрисовка screen.fill(BLACK) all_sprites.draw(screen)
Теперь в процессе создания любого спрайта нужно удостовериться, что он добавляется в категорию all_sprites. Отрисовка подобного спрайта на экране будет производиться автоматически. То же самое и относится к его обновлению в цикле.
Информацию о том, что делает каждый фрагмент приведенного выше кода, вы можете получить в комментариях, обозначенных символом #.
Как создать спрайт?
Сейчас можно приступать к созданию спрайта. В рассматриваемой нами библиотеки все они являются объектами, ибо Python — объектно-ориентированный язык программирования. Если прежде с этим типом данных вы не работали, то достаточно понимать, что с помощью объектов удобно осуществлять группировку объектов и кода в что-то единое.
Изначально это может запутывать, но через некоторое время станет понятно, насколько простая у объектов логика, и как они облегчают жизнь. И Pygame – отличный способ потренироваться в объектно-ориентированном программировании.
Что касается спрайтов, то они, как и любые другие объекты, имеют все характеристики: наследование, инкапсуляция, полиморфизм. Но об этом стоит поговорить уже отдельно.
Для начала попробуем определить новый спрайт.
class Player(pygame.sprite.Sprite):
Class говорит Python, что нужно определить спрайт игрока, который будет выступать в качестве нового объекта. Его тип — pygame.sprite.Sprite. Это означает, что он базируется на Sprite по умолчанию в Pygame.
При определении класса в первую очередь необходима специальная функция __init__(), которая включает инструкции, которые будет выполнять интерпретатор Python при генерации объекта данного типа. Кроме того, каждый спрайт в Pygame должен иметь два свойства: image и rect.
class Player(pygame.sprite.Sprite): def __init__(self): pygame.sprite.Sprite.__init__(self) self.image = pygame.Surface((50, 50)) self.image.fill(GREEN) self.rect = self.image.get_rect()
Первая строка Pygame.sprite.Sprite.__init__(self) обязательна в Pygame — она включает встроенный инициализатор класса Sprite. Затем вам нужно задать свойство image. А пока создаем квадрат 50×50 и заливаем его в зеленый цвет (то бишь, green). Чуть позже вы поймете, каким образом осуществляется изменение внешнего вида спрайта с помощью, например, человека или космического корабля, а пока хватит одного квадрата.
Затем вам нужно задать rect спрайта. Это означает прямоугольник. Они применяются в Pygame для понимания координат, в которых расположены конкретные объекты. Инструкция get_rect() оценивает изображение и вычисляет окружающий его прямоугольник.
rect можно применять для задания любого местоположения спрайта, доступного разработчику. Начнем с создания центрированного спрайта:
class Player(pygame.sprite.Sprite): def __init__(self): pygame.sprite.Sprite.__init__(self) self.image = pygame.Surface((50, 50)) self.image.fill(GREEN) self.rect = self.image.get_rect() self.rect.center = (WIDTH / 2, HEIGHT / 2
Теперь, после того, как мы определили спрайт игрока Player, необходимо создать его. Для этого инициализируется экземпляр одноименного класса. Помимо этого, необходимо в обязательном порядке добавить спрайт в группу с названием all_sprites.
all_sprites = pygame.sprite.Group() player = Player() all_sprites.add(player)
Теперь, при запуске приложения, в центре мы увидим зеленый квадрат. Если изменять значения WIDTH и HEIGHT в настройках приложения, можно обеспечить достаточное количество пространства для того, чтобы в следующем шаге сделать этот спрайт двигающимся.
Как заставить спрайт двигаться?
В игровом цикле можно воспользоваться функцией all_sprites.update(), которая запускает функцию update() всех спрайтов. Чтобы заставить спрайт перемещаться, необходимо задать правила, по которым будет осуществляться его обновление.
class Player(pygame.sprite.Sprite): def __init__(self): pygame.sprite.Sprite.__init__(self) self.image = pygame.Surface((50, 50)) self.image.fill(GREEN) self.rect = self.image.get_rect() self.rect.center = (WIDTH / 2, HEIGHT / 2) def update(self): self.rect.x += 5
Это означает, что при каждом игровом цикле x-координата спрайта будет изменяться на 5 пикселей в большую сторону. Теперь давайте попробуем запустить приложение, чтобы проверить, как он прячется за пределами экрана, достигая правой стороны.
Видим, что спрайт достигает правой стороны, и исчезает. Точнее, он просто оказывается за пределами области видимости. Чтобы исправить такую проблему, необходимо заставить спрайт двигаться по кругу. После того, как он достигает правой стороны экрана, он просто перемещается влево. Это на практике реализуется с использованием элемента управления rect спрайта.
Проще говоря, если левая сторона прямоугольника пропадает с экрана, то тогда просто нужно задать значение правого края на уровне 0.
class Player(pygame.sprite.Sprite): def __init__(self): pygame.sprite.Sprite.__init__(self) self.image = pygame.Surface((50, 50)) self.image.fill(GREEN) self.rect = self.image.get_rect() self.rect.center = (WIDTH / 2, HEIGHT / 2) def update(self): self.rect.x += 5 if self.rect.left > WIDTH: self.rect.right = 0
После этого, вы увидите, что спрайт начинает двигаться по кругу.
В принципе, мы реализовали базовую задачу, которую мы поставили для достижения целей этого урока. Теперь просто необходимо потренироваться в том, чтобы изменять координаты объектов спрайтов, перемещать их. При этом важно помнить, что все элементы, размещаемые в методы update(), будут находиться в каждом кадре, который есть в игре.
Какое можно придумать упражнение для закрепления этих знаний? Например, попробовать научить спрайт двигаться не слева направо, как в рассмотренном нами примере, а по вертикали. Или же можно его заставить отталкиваться от стен. Знаний, полученных в этом уроке, должно быть достаточно для того, чтобы достичь любой из этих целей.
Код урока
А теперь приведем итоговый код программы, выполняющей описанные в этом уроке задачи.
# Pygame шаблон - скелет для нового проекта Pygame import pygame import random WIDTH = 800 HEIGHT = 650 FPS = 30 # Задаем цвета WHITE = (255, 255, 255) BLACK = (0, 0, 0) RED = (255, 0, 0) GREEN = (0, 255, 0) BLUE = (0, 0, 255) class Player(pygame.sprite.Sprite): def __init__(self): pygame.sprite.Sprite.__init__(self) self.image = pygame.Surface((50, 50)) self.image.fill(GREEN) self.rect = self.image.get_rect() self.rect.center = (WIDTH / 2, HEIGHT / 2) def update(self): self.rect.x += 5 if self.rect.left > WIDTH: self.rect.right = 0 # Создаем игру и окно pygame.init() pygame.mixer.init() screen = pygame.display.set_mode((WIDTH, HEIGHT)) pygame.display.set_caption("My Game") clock = pygame.time.Clock() all_sprites = pygame.sprite.Group() player = Player() all_sprites.add(player) # Цикл игры running = True while running: # Держим цикл на правильной скорости clock.tick(FPS) # Ввод процесса (события) for event in pygame.event.get(): # check for closing window if event.type == pygame.QUIT: running = False # Обновление all_sprites.update() # Рендеринг screen.fill(BLACK) all_sprites.draw(screen) # После отрисовки всего, переворачиваем экран pygame.display.flip() pygame.quit()
В следующем уроке речь пойдет о том, как использовать арт в спрайтах — перейти от обычного квадрата к анимированному персонажу.
А далее мы более подробно поговорим о спрайтах и том, как с ними работать.