Руководство по pygame на русском

Время на прочтение
6 мин

Количество просмотров 58K

Это первая часть серии руководств «Разработка игр с помощью Pygame». Она предназначена для программистов начального и среднего уровней, которые заинтересованы в создании игр и улучшении собственных навыков кодирования на Python.

Что такое Pygame?

Pygame — это «игровая библиотека», набор инструментов, помогающих программистам создавать игры. К ним относятся:

  • Графика и анимация

  • Звук (включая музыку)

  • Управление (мышь, клавиатура, геймпад и так далее)

Игровой цикл

В сердце каждой игры лежит цикл, который принято называть «игровым циклом». Он запускается снова и снова, делая все, чтобы работала игра. Каждый цикл в игре называется кадром.

В каждом кадре происходит масса вещей, но их можно разбить на три категории:

1.Обработка ввода (события)

Речь идет обо всем, что происходит вне игры — тех событиях, на которые она должна реагировать. Это могут быть нажатия клавиш на клавиатуре, клики мышью и так далее.

2.Обновление игры

Изменение всего, что должно измениться в течение одного кадра. Если персонаж в воздухе, гравитация должна потянуть его вниз. Если два объекта встречаются на большой скорости, они должны взорваться.

3.Рендеринг (прорисовка)

В этом шаге все выводится на экран: фоны, персонажи, меню. Все, что игрок должен видеть, появляется на экране в нужном месте.

Время

Еще один важный аспект игрового цикла — скорость его работы. Многие наверняка знакомы с термином FPS, который расшифровывается как Frames Per Second (или кадры в секунду). Он указывает на то, сколько раз цикл должен повториться за одну секунду. Это важно, чтобы игра не была слишком медленной или быстрой. Важно и то, чтобы игра не работала с разной скоростью на разных ПК. Если персонажу необходимо 10 секунд на то, чтобы пересечь экран, эти 10 секунд должны быть неизменными для всех компьютеров.

Создание шаблона Pygame

Теперь, зная из каких элементов состоит игра, можно переходить к процессу написания кода. Начать стоит с создания простейшей программы pygame, которая всего лишь открывает окно и запускает игровой цикл. Это отправная точка для любого проекта pygame.

В начале программы нужно импортировать необходимые библиотеки и задать базовые переменные настроек игры:

# Pygame шаблон - скелет для нового проекта Pygame
import pygame
import random

WIDTH = 360  # ширина игрового окна
HEIGHT = 480 # высота игрового окна
FPS = 30 # частота кадров в секунду

Дальше необходимо открыть окно игры:

# создаем игру и окно
pygame.init()
pygame.mixer.init()  # для звука
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("My Game")
clock = pygame.time.Clock()

pygame.init() — это команда, которая запускает pygame. screen — окно программы, которое создается, когда мы задаем его размер в настройках. Дальше необходимо создать clock, чтобы убедиться, что игра работает с заданной частотой кадров.

Теперь необходимо создать игровой цикл:

# Цикл игры
running = True
while running:
    # Ввод процесса (события)
    # Обновление
    # Визуализация (сборка)

Игровой цикл — это цикл while, контролируемый переменной running. Если нужно завершить игру, необходимо всего лишь поменять значение running на False. В результате цикл завершится. Теперь можно заполнить каждый раздел базовым кодом.

Раздел рендеринга (отрисовки)

Начнем с раздела отрисовки. Персонажей пока нет, поэтому экран можно заполнить сплошным цветом. Чтобы сделать это, нужно разобраться, как компьютер обрабатывает цвета.

Экраны компьютеров сделаны из пикселей, каждый из которых содержит 3 элемента: красный, зеленый и синий. Цвет пикселя определяется тем, как горит каждый из элементов:

Каждый из трех основных цветов может иметь значение от 0 (выключен) до 255 (включен на 100%), так что для каждого элемента есть 256 вариантов.

Узнать общее количество отображаемых компьютером цветов можно, умножив:

>>> 256 * 256 * 256
16,777,216

Теперь, зная, как работают цвета, можно задать их в начале программ:

# Цвета (R, G, B)
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)

А после этого — заполнить весь экран.

    # Рендеринг
    screen.fill(BLACK)

Но этого недостаточно. Дисплей компьютера работает не так. Изменить пиксель — значит передать команду видеокарте, чтобы она передала соответствующую команду экрану. По компьютерным меркам это очень медленный процесс. Если нужно нарисовать на экране много всего, это займет много времени. Исправить это можно оригинальным способом, который называется — двойная буферизация. Звучит необычно, но вот что это такое.

Представьте, что у вас есть двусторонняя доска, которую можно поворачивать, показывая то одну, то вторую сторону. Одна будет дисплеем (то, что видит игрок), а вторая — оставаться скрытой, ее сможет «видеть» только компьютер. С каждым кадром рендеринг будет происходить на задней части доски. Когда отрисовка завершается, доска поворачивается и ее содержимое демонстрируется игроку.

А это значит, что процесс отрисовки происходит один раз за кадр, а не при добавлении каждого элемента.

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

    # Рендеринг
    screen.fill(BLACK)
    # после отрисовки всего, переворачиваем экран
    pygame.display.flip()

Главное — сделать так, чтобы функция flip() была в конце. Если попытаться отрисовать что-то после поворота, это содержимое не отобразится на экране.

Раздел ввода (событий)

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

События происходят постоянно. Что, если игрок нажимает кнопку прыжка во время отрисовки? Это нельзя игнорировать, иначе игрок будет разочарован. Для этого pygame сохраняет все события, произошедшие с момента последнего кадра. Даже если игрок будет лупить по кнопкам, вы не пропустите ни одну из них. Создается список, и с помощью цикла for можно пройтись по всем из них.

    for event in pygame.event.get():
        # проверить закрытие окна
        if event.type == pygame.QUIT:
            running = False

В pygame много событий, на которые он способен реагировать. pygame.QUIT — событие, которое стартует после нажатия крестика и передает значение False переменной running, в результате чего игровой цикл заканчивается.

Контроль FPS

Пока что нечего поместить в раздел Update (обновление), но нужно убедиться, что настройка FPS контролирует скорость игры. Это можно сделать следующим образом:

while running:
    # держим цикл на правильной скорости
    clock.tick(FPS)

Команда tick() просит pygame определить, сколько занимает цикл, а затем сделать паузу, чтобы цикл (целый кадр) длился нужно время. Если задать значение FPS 30, это значит, что длина одного кадра — 1/30, то есть 0,03 секунды. Если цикл кода (обновление, рендеринг и прочее) занимает 0,01 секунды, тогда pygame сделает паузу на 0,02 секунды.

Итог

Наконец, нужно убедиться, что когда игровой цикл завершается, окно игры закрывается. Для этого нужно поместить функцию pygame.quit() в конце кода. Финальный шаблон pygame будет выглядеть вот так:

# Pygame шаблон - скелет для нового проекта Pygame
import pygame
import random

WIDTH = 360
HEIGHT = 480
FPS = 30
# Задаем цвета
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
# Создаем игру и окно
pygame.init()
pygame.mixer.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("My Game")
clock = pygame.time.Clock()
# Цикл игры
running = True
while running:
    # Держим цикл на правильной скорости
    clock.tick(FPS)
    # Ввод процесса (события)
    for event in pygame.event.get():
        # check for closing window
        if event.type == pygame.QUIT:
            running = False
<span style="box-sizing: border-box; font-weight: inherit !important; font-size: inherit; padding-left: 0px; color: rgb(152, 143, 129);" class="token comment"># Обновление</span>

<span style="box-sizing: border-box; font-weight: inherit !important; font-size: inherit; padding-left: 0px; color: rgb(152, 143, 129);" class="token comment"># Рендеринг</span>
screen<span style="box-sizing: border-box; font-weight: inherit !important; font-size: inherit; color: rgb(168, 160, 149);" class="token punctuation">.</span>fill<span style="box-sizing: border-box; font-weight: inherit !important; font-size: inherit; color: rgb(168, 160, 149);" class="token punctuation">(</span>BLACK<span style="box-sizing: border-box; font-weight: inherit !important; font-size: inherit; color: rgb(168, 160, 149);" class="token punctuation">)</span>
<span style="box-sizing: border-box; font-weight: inherit !important; font-size: inherit; padding-left: 0px; color: rgb(152, 143, 129);" class="token comment"># После отрисовки всего, переворачиваем экран</span>
pygame<span style="box-sizing: border-box; font-weight: inherit !important; font-size: inherit; color: rgb(168, 160, 149);" class="token punctuation">.</span>display<span style="box-sizing: border-box; font-weight: inherit !important; font-size: inherit; color: rgb(168, 160, 149);" class="token punctuation">.</span>flip<span style="box-sizing: border-box; font-weight: inherit !important; font-size: inherit; color: rgb(168, 160, 149);" class="token punctuation">(</span><span style="box-sizing: border-box; font-weight: inherit !important; font-size: inherit; color: rgb(168, 160, 149);" class="token punctuation">)</span>

pygame.quit()

Ура! У вас есть рабочий шаблон Pygame. Сохраните его в файле с понятным названием, например, pygame_template.py, чтобы можно было использовать его каждый раз при создании нового проекта pygame.

В следующем руководстве этот шаблон будет использован как отправная точка для изучения процесса отрисовки объектов на экране и их движения.

Python — самый популярный язык программирования нового поколения. Во всех новых областях компьютерных наук Python активно присутствует. Python имеет обширные библиотеки для различных областей, таких как машинное обучение (Numpy, Pandas, Matplotlib), искусственный интеллект (Pytorch, TensorFlow) и разработка игр (Pygame, Pyglet).

Учебник по Python Pygame

В этом уроке мы узнаем о разработке игр и рассмотрим возможности программирования с использованием Pygame (библиотека Python).

  • Pygame в Python— это кроссплатформенный набор модулей Python, который используется для создания видеоигр.
  • Он состоит из компьютерной графики и звуковых библиотек, предназначенных для использования с языком программирования Python.
  • Pygame был официально написан Питом Шиннерсом для замены PySDL.
  • Pygame подходит для создания клиентских приложений, которые потенциально могут быть упакованы в автономный исполняемый файл.

Прежде чем изучать pygame, нам нужно понять, какую игру мы хотим разработать. Чтобы изучить pygame, необходимо иметь базовые знания Python.

Установка pygame в Windows

Перед установкой Pygame в системе должен быть установлен Python, желательно версии 3.6.1 или выше, потому что она намного удобнее для новичков и, кроме того, работает быстрее. В основном есть два способа установить Pygame, которые приведены ниже:

1. Установка через pip. Хороший способ установить Pygame — использовать инструмент pip (применяется в Python для установки пакетов). Команда следующая:

 
py -m pip install -U pygame --user 

2. Установка через IDE. Второй способ — установить его через IDE, и здесь мы используем Pycharm IDE. Установка pygame в pycharm проста. Мы можем установить его, выполнив указанную выше команду в терминале или выполнив следующие шаги:

  • Откройте вкладку «Файл» и нажмите «Настройки».

Установка Pygame через IDE

  • Выберите интерпретатор проекта и щелкните значок +.

Выбор интерпретатора проекта

  • Он отобразит окно поиска. Найдите pygame и нажмите кнопку установки пакета.

Установка пакета

Чтобы проверить, правильно ли установлен pygame, в интерпретаторе IDLE введите следующую команду и нажмите Enter:

 
import pygame 

Если команда выполняется успешно без каких-либо ошибок, это означает, что мы успешно установили Pygame и нашли правильную версию IDLE для использования в программировании pygame.

Проверка установки

Установка pygame на Mac

Чтобы установить pygame на Mac, выполните следующие действия.

  • Посетите официальный сайт pygame pygame.org и в следующем окне загрузите pygame-1.9.1release-python.org-32bit-py2.7-macosx10.3.dmg:

Установка pygame на Mac

Примечание. Если вы используете другую версию Python, загрузите последнюю ссылку.

  • Дважды щелкните загруженный файл и разархивируйте его. Теперь дважды щелкните распакованный файл mpkg, чтобы запустить программу установки. Следуйте инструкциям по установке pygame.
  • Запустите терминал (Cmd+Пробел, затем введите «терминал» в поле поиска). В терминале введите «python2.7» и нажмите Enter.
  • Python должен запуститься, отобразить версию 2.7.2 (2.7.1 тоже подойдет) и выдать подсказку. В командной строке Python введите «import pygame». Если вы не получаете никаких ошибок, все работает нормально.

Простой пример pygame

Вот простая программа pygame, которая дает общее представление о синтаксисе.

 
import pygame 
 
pygame.init() 
screen = pygame.display.set_mode((400,500)) 
done = False 
 
while not done: 
    for event in pygame.event.get(): 
        if event.type == pygame.QUIT: 
            done = True 
    pygame.display.flip() 

Выход:

После успешного выполнения он выдаст следующее окно в качестве вывода:

Вывод

Давайте разберемся с основным синтаксисом приведенной выше программы построчно:

  • import pygame — обеспечивает доступ к фреймворку pygame и импортирует все функции pygame.
  • pygame.init() — используется для инициализации всех необходимых модулей pygame.
  • pygame.display.set_mode((width, height)) — используется для отображения окна нужного размера. Возвращаемое значение — это объект Surface, который является объектом, в котором мы будем выполнять графические операции.
  • pygame.event.get() — очищает очередиь событий. Если мы не назовем это, оконные сообщения начнут накапливаться, и игра перестанет отвечать на запросы операционной системы.
  • pygame.QUIT — используется для завершения события, когда мы нажимаем кнопку закрытия в углу окна.
  • pygame.display.flip() — Pygame использует двойную буферизацию, поэтому буферы смещаются. Очень важно вызвать эту функцию, чтобы сделать видимыми любые обновления, которые вы делаете на игровом экране.

Surface Pygame

Поверхность pygame используется для отображения любого изображения. Pygame имеет предустановленное разрешение и формат пикселей. Цвет поверхности по умолчанию черный. Его размер определяется передачей аргумента размера.

Поверхности могут иметь ряд дополнительных атрибутов, таких как альфа-плоскости, цветовые ключи, отсечение исходного прямоугольника и другие. Подпрограммы blit будут пытаться использовать аппаратное ускорение, когда это возможно; в противном случае они будут использовать усовершенствованные методы копирования программного обеспечения.

Pygame часы

Время представлено в миллисекундах (1/1000 секунды) в pygame. Часы Pygame используются для отслеживания времени. Время необходимо для создания движения, воспроизведения звука или реакции на любое событие. В общем, мы не считаем время в секундах. Считаем в миллисекундах. Часы также предоставляют различные функции, помогающие контролировать частоту кадров в игре. Имеют несколько функций:

  • tick()

Эта функция используется для обновления часов. Синтаксис следующий:

 
tick(framerate=0) 

Данный метод следует вызывать один раз за кадр. Он подсчитает, сколько миллисекунд прошло с момента предыдущего вызова. Аргумент частоты кадров является необязательным для передачи в функцию, и если он передается в качестве аргумента, функция будет делать задержку, чтобы игра работала медленнее, чем заданное количество тактов в секунду.

  • tick_busy_loop()

Функция tick_busy_loop() аналогична функции tick(). При вызове Clock.tick_busy_loop(20) один раз за кадр программа никогда не будет работать со скоростью более 20 кадров в секунду. Синтаксис следующий:

 
tick_busy_loop() 
  • get_time()

get_time() используется для получения предыдущего тика. Число миллисекунд, которое isdra прошло между двумя последними вызовами в Clock.tick().

 
get_time() 

Что такое Pygame Blit в Python?

Блиттинг pygame в Python — это процесс рендеринга игрового объекта на поверхность, и этот процесс называется блиттингом. Когда мы создаем игровой объект, нам нужно его визуализировать. Если мы не отрендерим игровые объекты и не запустим программу, то на выходе она выдаст черное окно.

Блиттинг — одна из самых медленных операций в любой игре, поэтому нам нужно быть осторожными, чтобы не сильно блитить на экране в каждом кадре. Основная функция, используемая в блиттинге, — это blit(), а именно:

 
blit(source,dest,area=None,special_flags=0) 

Эта функция используется для вставки одного изображения в другое. Может быть размещена с аргументом dest. Аргумент dest может быть парой координат, представляющих левый верхний угол источника.

Добавление изображения

Чтобы добавить изображение в окно, сначала нам нужно создать пустую поверхность, вызвав конструктор Surface с кортежем ширины и высоты.

 
surface = pygame.Surface((100,100)) 

Приведенная выше строка создает пустое 24-битное изображение RGB размером 100*100 пикселей с черным цветом по умолчанию.

Для прозрачной инициализации Surface передайте аргумент SRCALPHA.

 
surface = pygame.Surface((100,100), pygame.SRCALPHA) 

Рассмотрим следующий пример для отображения изображения на поверхности:

 
import pygame 
pygame.init() 
white =(255, 255, 255) 
# assigning values to height and width variable  
height = 400 
width = 400 
# creating the display surface object  
# of specific dimension..e(X, Y).  
display_surface = pygame.display.set_mode((height, width)) 
 
# set the pygame window name  
pygame.display.set_caption('Image') 
 
# creating a surface object, image is drawn on it.  
image = pygame.image.load(r'C:UsersDEVANSH SHARMADesktopdownload.png') 
 
# infinite loop  
while True: 
    display_surface.fill(white) 
    display_surface.blit(image,(0, 0)) 
 
    for event in pygame.event.get(): 
        if event.type == pygame.QUIT: 
            pygame.quit() 
            # quit the program.  
            quit() 
        # Draws the surface object to the screen.  
        pygame.display.update()  

Выход:

Добавление изображения в Pygame

Прямоугольник в Pygame

Rect используется для рисования прямоугольника в Pygame. Pygame использует объекты Rect для хранения прямоугольных областей и управления ими. Rect может быть сформирован из комбинации значений left, top, width и height. Его также можно создать из объектов Python, которые уже являются Rect или имеют атрибут с именем «rect».

Функция rect() используется для изменения положения или размера прямоугольника. Он возвращает новую копию Rect с затронутыми изменениями. Никаких изменений в исходном прямоугольнике не происходит.

Объект Rect имеет различные виртуальные атрибуты, которые можно использовать для перемещения и выравнивания:

 
x,y 
top, left, right, bottom 
topleft, bottomleft, topright, bottomright 
midtop, midleft, midbottom, midright 
center, centerx, centery 
size, width, height 
w,h 

Размер прямоугольника можно изменить, задав размер, ширину или высоту. Все остальные присваивания перемещают прямоугольник без изменения его размера.

Если ширина или высота являются ненулевым значением Rect, то для ненулевого теста будет возвращено значение True. Некоторые методы возвращают Rect с размерами 0 для представления недопустимого прямоугольника.

Давайте создадим Rectangle в окне pygame, используя Rect:

 
import pygame 
 
pygame.init() 
screen = pygame.display.set_mode((400, 300)) 
done = False 
 
while not done: 
    for event in pygame.event.get(): 
        if event.type == pygame.QUIT: 
            done = True 
    pygame.draw.rect(screen,(0, 125, 255), pygame.Rect(30, 30, 60, 60))   
 
    pygame.display.flip() 

После выполнения приведенного выше кода он отобразит прямоугольник в окне pygame.

Прямоугольник в Pygame

Клавиши Pygame

Pygame KEYDOWN и KEYUP обнаруживают событие, если клавиша физически нажата и отпущена. KEYDOWN определяет нажатие клавиши, KEYUP определяет ее отпускание. Оба события (нажатие клавиши и отпускание клавиши) имеют два следующих атрибута:

  • key: ключ — это целочисленный идентификатор, который представляет каждый ключ в ключевом слове.
  • mod: это битовая маска всех клавиш-модификаторов, которые были в нажатом состоянии, когда произошло событие.

Рассмотрим следующий пример нажатия и отпускания клавиши.

 
import pygame 
pygame.init() 
# sets the window title 
pygame.display.set_caption(u'Keyboard events') 
# sets the window size 
pygame.display.set_mode((400, 400)) 
 
while True: 
    # gets a single event from the event queue 
    event = pygame.event.wait() 
    # if the 'close' button of the window is pressed 
    if event.type == pygame.QUIT: 
        # stops the application 
        break 
    # Detects the 'KEYDOWN' and 'KEYUP' events 
    if event.type in(pygame.KEYDOWN, pygame.KEYUP): 
        # gets the key name 
        key_name = pygame.key.name(event.key) 
        # converts to uppercase the key name 
        key_name = key_name.upper() 
        # if any key is pressed 
        if event.type == pygame.KEYDOWN: 
            # prints on the console the key pressed 
            print(u'"{}" key pressed'.format(key_name)) 
        # if any key is released 
        elif event.type == pygame.KEYUP: 
            # prints on the console the released key 
            print(u'"{}" key released'.format(key_name)) 

Выход:

Клавиатура Pygame

Давайте посмотрим на другой пример:

 
import pygame 
 
pygame.init() 
screen = pygame.display.set_mode((400, 300)) 
done = False 
is_blue = True 
x = 30 
y = 30 
 
while not done: 
    for event in pygame.event.get(): 
        if event.type == pygame.QUIT: 
            done = True 
        if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE: 
            is_blue = not is_blue 
 
    pressed = pygame.key.get_pressed() 
    if pressed[pygame.K_UP]: y -= 3 
    if pressed[pygame.K_DOWN]: y += 3 
    if pressed[pygame.K_LEFT]: x -= 3 
    if pressed[pygame.K_RIGHT]: x += 3 
 
    if is_blue: 
        color =(0, 128, 255) 
    else:  
        color =(255, 100, 0) 
    pygame.draw.rect(screen, color, pygame.Rect(x, y, 60, 60)) 
 
    pygame.display.flip() 

В приведенном выше коде прямоугольник будет отображаться в окне pygame.

Прямоугольник в окне Pygame

Когда мы нажимаем клавишу «Вниз», прямоугольник меняет форму вниз. Вывод следующий:

Изменение с помощью клавиши Pygame

Pygame Draw

Pygame предоставляет функции геометрии для рисования простых фигур на поверхности. Эти функции будут работать для рендеринга в любой формат на поверхности. Большинство функций принимают аргумент ширины, чтобы обозначить размер толщины вокруг края фигуры. Если ширина передана 0, то форма будет сплошной (заполненной).

Все функции рисования принимают аргумент цвета, который может быть в одном из следующих форматов:

  • Объекты pygame.Color
  • Триплет(RGB)(кортеж/список)
  • Четверка(RGBA)(кортеж/список)
  • Целочисленное значение, сопоставленное с пиксельным форматом поверхности.

Рисование прямоугольника

Следующие функции используются для рисования прямоугольника на заданной поверхности.

 
pygame.draw.rect(surface, color, rect) 
pygame.draw.rect(surface, color, rect, width=0) 

Параметры:

  • Surface — экран для рисования.
  • color — этот аргумент используется для окрашивания заданной формы. Альфа-значение является необязательным, если мы используем кортеж.
  • rect(Rect) – рисование прямоугольника, положение и размеры.
  • width(int) — чтобы использовать толщину линии или указать, что прямоугольник заполнен, необязателен.
 
if width == 0,(default) fill the rectangle 
if width > 0, used for line thickness 
if width < 0, nothing will be drawn 

Рисование многоугольника

Следующие функции используются для рисования многоугольника на заданной поверхности.

  • pygame.draw.polygon(surface,color,points)
  • pygame.draw.polygon(surface, color, points, width=0)

Параметры:

  • Surface — экран для рисования.
  • color — этот аргумент используется для окрашивания заданной формы. Альфа-значение является необязательным, если мы используем кортеж.
  • points(tuple(coordinate) или list(coordinate)): последовательность из 3 или более(x, y) координат, составляющих вершины многоугольника. Каждая координата в последовательности должна быть кортежем/списком.

Примечание. – Если len(points) < 3 или точки не являются последовательностью или точки не содержат числовой пары, это вызовет ошибку значения.

Эллипс

Следующие функции используются для рисования эллипса на заданной поверхности.

 
pygame.draw.ellipse(surface, color, rect) 
pygame.draw.ellipse(surface, color, rect, width=0) 

Параметры:

  • Surface — экран для рисования.
  • color — этот аргумент используется для окрашивания заданной формы. Альфа-значение является необязательным, если мы используем кортеж.
  • rect(Rect) – рисование прямоугольника, положение и размеры.

Прямая линия

Этот метод используется для рисования прямой линии на заданной поверхности. Концовок нет.

 
pygame.draw.line(surface,color,start_pos,end_pos,width) 
pygame.draw.line(surface,color,start_pos,end_pos,width=1) 

Параметры:

  • Surface — экран для рисования.
  • color — этот аргумент используется для окрашивания заданной формы. Альфа-значение является необязательным, если мы используем кортеж.
  • start_pos — начальная позиция линии(x,y)
  • end_pos — конечная позиция строки.

Круг

Ниже приведены функции, которые используются для рисования окружности на заданной поверхности.

  • circle(surface, color, center, radius)
  • circle(surface, color, center, radius, width=0)

Параметры:

  • Surface — экран для рисования.
  • color — этот аргумент используется для окрашивания заданной формы. Альфа-значение является необязательным, если мы используем кортеж.
  • center – центральная точка круга как последовательность двух int/float, например(x,y)
  • radius(int или float) – радиус окружности, отсчитываемый от параметра center, если радиус равен нулю, то будет отрисовываться только центральный пиксель.

Эллиптическая дуга

Следующие функции используются для рисования эллиптической дуги на заданной поверхности.

 
?  arc(surface, color, rect, start_angle, stop_angle)  
?  arc(surface, color, rect, start_angle, stop_angle, width=1) 

Параметры:

  • Surface — экран для рисования.
  • color — этот аргумент используется для окрашивания заданной формы. Альфа-значение является необязательным, если мы используем кортеж.
  • rect(Rect) – рисование прямоугольника, его положение и размеры.
  • start_angle — начальный угол дуги в радианах.
  • stop_angle — конечный угол дуги в радианах.

Есть три условия для параметров start_angle и stop_angle:

  1. Если start_angle < stop_angle, то дуга будет нарисована против часовой стрелки от start_angle до end_angle.
  2. Если start_angle>stop_angle, то tau(tau=2*pi) будет добавлено к углу остановки.
  3. Если start_angle==stop_angle, ничего не будет нарисовано.

Рассмотрим пример:

 
import pygame 
from math import pi 
pygame.init() 
# size variable is using for set screen size 
size = [400, 300] 
screen = pygame.display.set_mode(size) 
pygame.display.set_caption("Example program to draw geometry") 
# done variable is using as flag  
done = False 
clock = pygame.time.Clock() 
while not done: 
    # clock.tick() limits the while loop to a max of 10 times per second. 
        clock.tick(10) 
 
    for event in pygame.event.get():  # User did something 
        if event.type == pygame.QUIT:  # If user clicked on close symbol  
            done = True  # done variable that we are complete, so we exit this loop 
 
    # All drawing code occurs after the for loop and but 
    # inside the main while done==False loop. 
 
    # Clear the default screen background and set the white screen background 
    screen.fill((0, 0, 0)) 
 
    # Draw on the screen a green line which is 5 pixels wide. 
    pygame.draw.line(screen,(0, 255, 0), [0, 0], [50, 30], 5) 
    # Draw on the screen a green line which is 5 pixels wide. 
    pygame.draw.lines(screen,(0, 0, 0), False, [[0, 80], [50, 90], [200, 80], [220, 30]], 5) 
 
    # Draw a rectangle outline 
    pygame.draw.rect(screen,(0, 0, 0), [75, 10, 50, 20], 2) 
 
    # Draw a solid rectangle 
    pygame.draw.rect(screen,(0, 0, 0), [150, 10, 50, 20]) 
 
    # This draw an ellipse outline, using a rectangle as the outside boundaries 
    pygame.draw.ellipse(screen,(255, 0, 0), [225, 10, 50, 20], 2) 
 
    # This draw a solid ellipse, using a rectangle as the outside boundaries 
    pygame.draw.ellipse(screen,(255, 0, 0), [300, 10, 50, 20]) 
 
    # Draw a triangle using the polygon function 
    pygame.draw.polygon(screen,(0, 0, 0), [[100, 100], [0, 200], [200, 200]], 5) 
 
    # This draw a circle 
    pygame.draw.circle(screen,(0, 0, 255), [60, 250], 40) 
 
    # This draw an arc 
    pygame.draw.arc(screen,(0, 0, 0), [210, 75, 150, 125], 0, pi / 2, 2) 
 
    # This function must write after all the other drawing commands. 
    pygame.display.flip() 
 
# Quite the execution when clicking on close 
pygame.quit() 

Выход:

Рисование в Pygame

Текст и шрифт Pygame

Pygame также предоставляет средства для рендеринга шрифта и текста. Мы можем загружать шрифты из системы с помощью функции pygame.font.SysFont(). Pygame поставляется со встроенным шрифтом по умолчанию, доступ к которому можно получить, передав имя шрифта или None. Есть множество функций, помогающих работать со шрифтом.

Объекты шрифта создаются с помощью pygame.font.Font(). Фактические объекты шрифта выполняют большую часть работы, выполняемой со шрифтами. Объекты шрифта обычно используются для рендеринга текста в новые объекты Surface. Вот несколько важных функций шрифта:

  • render()

Эта функция используется для рисования текста на новой поверхности. Pygame не имеет возможности рисовать текст на существующей поверхности. Это создает новую поверхность с указанным текстовым рендерингом на ней. Синтаксис следующий:

 
render(text, antialias, color, background=None) 
  • size()

Эта функция используется для определения количества пробелов или позиций, необходимых для отображения текста. Его также можно использовать для переноса слов и других эффектов макета. Синтаксис следующий:

 
size(bool) 
  • set_bold()

Эта функция используется для выделения текста жирным шрифтом. Синтаксис следующий:

 
set_bold(bool) 

Рассмотрим следующий пример:

 
import pygame 
pygame.init() 
screen = pygame.display.set_mode((640, 480)) 
done = False 
 
#load the fonts 
font = pygame.font.SysFont("Times new Roman", 72) 
# Render the text in new surface 
text = font.render("Hello, Pygame", True,(158, 16, 16)) 
while not done: 
    for event in pygame.event.get(): 
        if event.type == pygame.QUIT: 
            done = True 
        if event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE: 
            done = True 
    screen.fill((255, 255, 255)) 
    #We will discuss blit() in the next topic 
    screen.blit(text,(320 - text.get_width() // 2, 240 - text.get_height() // 2)) 
 
    pygame.display.flip() 

Выход:

Текст и шрифт Pygame

Примечание . Необходимо помнить, что определенный шрифт должен быть установлен на компьютере пользователя. Если вы не знаете, установлены шрифты или нет, у pygame есть следующая функция для перечисления всех доступных для пользователя шрифтов:

 
 all_font = pygame.font.get_fonts() 

Существует еще одна функция для создания экземпляра системного шрифта по умолчанию:

 
font = pygame.font.Font(None,size) 

Используя любые вышеперечисленные функции, мы можем работать с привлекательным шрифтом в игре.

Pygame Sprite и обнаружение столкновений

Sprite pygame — это двумерное изображение, являющееся частью большой графической сцены. Обычно Sprite представляет собой какой-то объект на сцене.

Одним из самых важных преимуществ работы со Sprite является возможность работать с ними в группах. Мы можем легко перемещать и рисовать их одной командой, если они находятся в группе.

Модуль Sprite содержит различные простые классы для использования в играх. Необязательно использовать классы Sprite и различные групповые классы при использовании pygame.

Pygame предоставляет спрайты и группы, которые помогают обнаруживать столкновения. Обнаружение столкновений — это процесс, когда два объекта на экране сталкиваются друг с другом. Например, если в игрока попала вражеская пуля, то он может потерять жизнь или программе нужно знать, когда игрок касается монеты, чтобы она автоматически подбиралась.

Рассмотрим следующий пример:

 
import pygame 
import sys 
#Sprite class  
class Sprite(pygame.sprite.Sprite): 
    def __init__(self, pos): 
        pygame.sprite.Sprite.__init__(self) 
        self.image = pygame.Surface([20, 20]) 
        self.image.fill((255, 0, 255)) 
        self.rect = self.image.get_rect() 
        self.rect.center = pos 
def main(): 
    pygame.init() 
    clock = pygame.time.Clock() 
    fps = 50 
    bg = [0, 0, 0] 
    size =[300, 300] 
    screen = pygame.display.set_mode(size) 
    player = Sprite([40, 50]) 
    # Define keys for player movement 
    player.move = [pygame.K_LEFT, pygame.K_RIGHT, pygame.K_UP, pygame.K_DOWN] 
    player.vx = 5 
    player.vy = 5 
 
    wall = Sprite([100, 60]) 
 
    wall_group = pygame.sprite.Group() 
    wall_group.add(wall) 
 
    player_group = pygame.sprite.Group() 
    player_group.add(player) 
 
    while True: 
        for event in pygame.event.get(): 
            if event.type == pygame.QUIT: 
                return False 
        key = pygame.key.get_pressed() 
        for i in range(2): 
            if key[player.move[i]]: 
                player.rect.x += player.vx * [-1, 1][i] 
 
        for i in range(2): 
            if key[player.move[2:4][i]]: 
                player.rect.y += player.vy * [-1, 1][i] 
        screen.fill(bg) 
        # first parameter takes a single sprite 
        # second parameter takes sprite groups 
        # third parameter is a kill command if true 
        hit = pygame.sprite.spritecollide(player, wall_group, True) 
        if hit: 
        # if collision is detected call a function to destroy 
            # rect 
            player.image.fill((255, 255, 255)) 
        player_group.draw(screen) 
        wall_group.draw(screen) 
        pygame.display.update() 
        clock.tick(fps) 
    pygame.quit() 
    sys.exit 
if __name__ == '__main__': 

Выход:

Обнаружение столкновений

После нажатия клавиш со стрелками один прямоугольник столкнется с другим прямоугольником, после чего выводится:

Столкновение

Pyglet

Python предоставляет еще одну игровую библиотеку под названием pyglet, которая представляет собой кроссплатформенную библиотеку окон и мультимедиа для Python. Она используется для разработки игр и других визуально насыщенных приложений.

Pyglet поддерживает обработку событий пользовательского интерфейса, работу с окнами, графику OpenGL, загрузку изображений и видео, а также воспроизведение звуков и музыки.

Вот несколько особенностей pyglet:

  • Никаких внешних требований к установке или зависимостей.
  • Воспользуйтесь преимуществами нескольких окон и нескольких мониторов.
  • Он может загружать изображения, звук, музыку и видео в любом формате.
  • Pyglet предоставляется под лицензией BSD с открытым исходным кодом.
  • Он поддерживает как Python 2, так и 3.

Установка pyglet проста; его можно установить, введя следующую команду.

 
pip install pyglet 

Рассмотрим следующий пример.

 
import pyglet 
window = pyglet.window.Window() 
lable = pyglet.text.Label('Hello world', font_name='Times New Roman', font_size=36, 
                          x= window.width//2,y=window.height//2,anchor_x='center', anchor_y='center') 
@window.event 
def on_draw(): 
    window.clear() 
    lable.draw() 
pyglet.app.run() 

Выход:

Pyglet

Сравнение между Pygame и Pyglet

Pyglet Pygame
3D поддержка

Поскольку pyglet так прочно слился с OpenGL, это позволяет поддерживать рисунок в 3D.

Простой синтаксис Python

Pygame использует Python в качестве языка сценариев. Python считается одним из самых естественных языков для понимания даже новичками.

Кроссплатформенность

Он может работать с Windows, Linux и OS X.

Использование API

API очень простой.

Написан на чистом Python

Его можно скомпилировать с помощью других интерпретаторов Python.

Лучшая система рисования

Pygame предоставляет систему рисования, которая позволяет пользователю создавать и рисовать неограниченное количество холстов.

Меньше популярности

Pyglet менее популярен, потому что у него небольшая поддержка сообщества.

Более популярный

Pygame более популярен, чем pyglet.

В этом руководстве мы обсудили простой подход к программированию разработки игр, установив модуль pygame с открытым исходным кодом в среду программирования Python 3.

Изучаю Python вместе с вами, читаю, собираю и записываю информацию опытных программистов.

Когда я начал изучать компьютерное программирование в конце прошлого тысячелетия, это было связано с моим желанием писать компьютерные игры. Я пытался понять, как писать игры на каждом языке и на каждой изученной платформе, включая Python. Так я открыл для себяpygame и научился использовать его для написания игр и других графических программ. В то время мне очень хотелось получить учебник поpygame.

К концу этой статьи вы сможете:

  • Нарисуйте предметы на вашем экране

  • Воспроизведение звуковых эффектов и музыки

  • Обрабатывать пользовательский ввод

  • Реализация циклов событий

  • Опишите, чем игровое программирование отличается от стандартного процедурного программирования на Python

Вы можете получить весь код в этой статье, чтобы следовать:

Фон и настройка

pygame — это оболочка Python дляSDL library, что означаетSimple DirectMedia Layer. SDL обеспечивает кроссплатформенный доступ к базовым компонентам мультимедийного оборудования вашей системы, таким как звук, видео, мышь, клавиатура и джойстик. pygame начал свою жизнь как замена остановившемусяPySDL project. Кросс-платформенный характер как SDL, так иpygame означает, что вы можете писать игры и мультимедийные программы Python для любой платформы, которая их поддерживает!

Чтобы установитьpygame на вашу платформу, используйте соответствующую командуpip:

Вы можете проверить установку, загрузив один из примеров, поставляемых с библиотекой:

$ python3 -m pygame.examples.aliens

Если появляется окно игры, значитpygame установлен правильно! Если у вас возникнут проблемы, тоGetting Started guide описывает некоторые известные проблемы и предостережения для всех платформ.

Основная программа PyGame

Прежде чем переходить к деталям, давайте взглянем на базовую программуpygame. Эта программа создает окно, заполняет фон белым и рисует синий круг в середине:

 1 # Simple pygame program
 2
 3 # Import and initialize the pygame library
 4 import pygame
 5 pygame.init()
 6
 7 # Set up the drawing window
 8 screen = pygame.display.set_mode([500, 500])
 9
10 # Run until the user asks to quit
11 running = True
12 while running:
13
14     # Did the user click the window close button?
15     for event in pygame.event.get():
16         if event.type == pygame.QUIT:
17             running = False
18
19     # Fill the background with white
20     screen.fill((255, 255, 255))
21
22     # Draw a solid blue circle in the center
23     pygame.draw.circle(screen, (0, 0, 255), (250, 250), 75)
24
25     # Flip the display
26     pygame.display.flip()
27
28 # Done! Time to quit.
29 pygame.quit()

Когда вы запустите эту программу, вы увидите окно, которое выглядит так:

A simple pygame program

Давайте разберем этот код, раздел за разделом:

  • Lines 4 and 5 импортирует и инициализирует библиотекуpygame. Без этих строк нетpygame.

  • Line 8 устанавливает окно отображения вашей программы. Вы предоставляете либо список, либо кортеж, который определяет ширину и высоту создаваемого окна. Эта программа использует список для создания квадратного окна с 500 пикселями на каждой стороне.

  • Lines 11 and 12 настраиваетgame loop для контроля завершения программы. Об этом вы узнаете позже в этом уроке.

  • Lines 15 to 17 просматривает и обрабатываетevents в игровом цикле. Вы придете к событиям чуть позже. В этом случае обрабатывается только событиеpygame.QUIT, которое происходит, когда пользователь нажимает кнопку закрытия окна.

  • Line 20 заполняет окно сплошным цветом. screen.fill() принимает либо список, либо кортеж, определяющий значения RGB для цвета. Поскольку(255, 255, 255) предоставлен, окно заполняется белым цветом.

  • Line 23 рисует круг в окне, используя следующие параметры:

    • screen: окно, в котором нужно рисовать

    • (0, 0, 255): кортеж, содержащий значения цвета RGB

    • (250, 250): кортеж, определяющий координаты центра круга

    • 75: радиус нарисованного круга в пикселях

  • Line 26 обновляет содержимое дисплея на экране. Без этого звонка в окне ничего не появляется!

  • Line 29 выходит изpygame. Это происходит только после завершения цикла.

Этоpygame версия «Hello, World». Теперь давайте углубимся в концепции, лежащие в основе этого кода.

PyGame Concepts

Посколькуpygame и библиотека SDL переносимы на разные платформы и устройства, они оба должны определять абстракции и работать с ними для различных аппаратных реалий. Понимание этих концепций и абстракций поможет вам спроектировать и разработать свои собственные игры.

Инициализация и Модули

Библиотекаpygame — этоcomposed of a number of Python constructs, которая включает несколько разныхmodules. Эти модули обеспечивают абстрактный доступ к конкретному оборудованию в вашей системе, а также унифицированные методы для работы с этим оборудованием. Например,display обеспечивает единообразный доступ к вашему видео дисплею, аjoystick позволяет абстрактно управлять вашим джойстиком.

После импорта библиотекиpygame в приведенном выше примере первое, что вы сделали, — этоinitialize PyGame с использованиемpygame.init(). Эта функцияcalls the separate init() functions всех включенных модулейpygame. Поскольку эти модули являются абстракциями для конкретного оборудования, этот шаг инициализации необходим для того, чтобы вы могли работать с одним и тем же кодом в Linux, Windows и Mac.

Дисплеи и поверхности

В дополнение к модулямpygame также включает несколько Pythonclasses, которые инкапсулируют концепции, не зависящие от оборудования. Один из них —Surface, который, по сути, определяет прямоугольную область, на которой вы можете рисовать. ОбъектыSurface используются во многих контекстах вpygame. Позже вы увидите, как загрузить изображение вSurface и отобразить его на экране.

Вpygame все просматривается на одном созданном пользователемdisplay, который может быть окном или полноэкранным. Отображение создается с использованием.set_mode(), который возвращаетSurface, представляющий видимую часть окна. Именно этотSurface вы передаете в функции рисования, такие какpygame.draw.circle(), и содержимое этогоSurface выводится на дисплей, когда вы вызываетеpygame.display.flip().

Изображения и Rects

Ваша базовая программаpygame нарисовала фигуру прямо на экранеSurface, но вы также можете работать с изображениями на диске. image module позволяет создавать изображенияload иsave в различных популярных форматах. Изображения загружаются в объектыSurface, которыми затем можно управлять и отображать различными способами.

Как упоминалось выше, объектыSurface представлены прямоугольниками, как и многие другие объекты вpygame, такие как изображения и окна. Прямоугольники настолько широко используются, что существуетspecial Rect class только для их обработки. Вы будете использовать объекты и изображенияRect в своей игре, чтобы рисовать игроков и врагов и управлять столкновениями между ними.

Ладно, достаточно теории. Давайте разработаем и напишем игру!

Базовый дизайн игры

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

  • Цель игры — избежать препятствий:

    • Плеер запускается с левой стороны экрана.

    • Препятствия входят случайным образом справа и движутся влево по прямой линии.

  • Игрок может двигаться влево, вправо, вверх или вниз, чтобы избежать препятствий.

  • Плеер не может отойти от экрана.

  • Игра заканчивается либо тогда, когда игрок сталкивается с препятствием, либо когда пользователь закрывает окно.

Когда он описывал программные проекты,former colleague of mine говорил: «Вы не знаете, что делаете, пока не узнаете, чего не делаете». Имея это в виду, вот некоторые вещи, которые не будут рассмотрены в этом руководстве:

  • Нет нескольких жизней

  • Нет счета

  • Нет возможности атаки игрока

  • Нет продвигающихся уровней

  • Нет боссов

Вы можете сами попробовать добавить эти и другие функции в свою программу.

Давайте начнем!

Импорт и инициализация PyGame

После импортаpygame вам также потребуется его инициализировать. Это позволяетpygame подключать свои абстракции к вашему конкретному оборудованию:

 1 # Import the pygame module
 2 import pygame
 3
 4 # Import pygame.locals for easier access to key coordinates
 5 # Updated to conform to flake8 and black standards
 6 from pygame.locals import (
 7     K_UP,
 8     K_DOWN,
 9     K_LEFT,
10     K_RIGHT,
11     K_ESCAPE,
12     KEYDOWN,
13     QUIT,
14 )
15
16 # Initialize pygame
17 pygame.init()

Библиотекаpygame определяет многие вещи помимо модулей и классов. Он также определяет некоторыеlocal constants для таких вещей, как нажатия клавиш, движения мыши и атрибуты отображения. Вы ссылаетесь на эти константы, используя синтаксисpygame.<CONSTANT>. Импортируя определенные константы изpygame.locals, вы можете вместо этого использовать синтаксис<CONSTANT>. Это сэкономит вам несколько нажатий клавиш и улучшит общую читабельность.

Настройка дисплея

Теперь вам нужно что-то нарисовать! Создайтеscreen как общий холст:

 1 # Import the pygame module
 2 import pygame
 3
 4 # Import pygame.locals for easier access to key coordinates
 5 # Updated to conform to flake8 and black standards
 6 from pygame.locals import (
 7     K_UP,
 8     K_DOWN,
 9     K_LEFT,
10     K_RIGHT,
11     K_ESCAPE,
12     KEYDOWN,
13     QUIT,
14 )
15
16 # Initialize pygame
17 pygame.init()
18
19 # Define constants for the screen width and height
20 SCREEN_WIDTH = 800
21 SCREEN_HEIGHT = 600
22
23 # Create the screen object
24 # The size is determined by the constant SCREEN_WIDTH and SCREEN_HEIGHT
25 screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))

Вы создаете экран для использования, вызываяpygame.display.set_mode() и передавая кортеж или список с желаемой шириной и высотой. В этом случае размер окна составляет 800×600, что определяется константамиSCREEN_WIDTH иSCREEN_HEIGHT в строках 20 и 21. Это возвращаетSurface, который представляет внутренние размеры окна. Это часть окна, которой вы можете управлять, в то время как ОС контролирует границы окна и строку заголовка.

Если вы запустите эту программу сейчас, вы увидите, что окно ненадолго всплывет, а затем сразу исчезнет при выходе из программы. Не моргайте, иначе вы можете пропустить это! В следующем разделе вы сосредоточитесь на основном игровом цикле, чтобы гарантировать, что ваша программа завершает работу только при правильном вводе.

Настройка игрового цикла

В каждой игре от Pong до Fortnite используетсяgame loop для управления игровым процессом. Игровой цикл выполняет четыре очень важных вещи:

  1. Обрабатывает пользовательский ввод

  2. Обновляет состояние всех игровых объектов

  3. Обновляет дисплей и аудио выход

  4. Поддерживает скорость игры

Каждый цикл игрового цикла называетсяframe, и чем быстрее вы сможете выполнять действия в каждом цикле, тем быстрее будет работать ваша игра. Кадры продолжают появляться до тех пор, пока не будет выполнено какое-либо условие для выхода из игры. В вашем дизайне есть два условия, которые могут завершить игровой цикл:

  1. Игрок сталкивается с препятствием. (Вы узнаете об обнаружении столкновений позже.)

  2. Игрок закрывает окно.

Первое, что делает игровой цикл, это обрабатывает пользовательский ввод, чтобы позволить игроку перемещаться по экрану. Поэтому вам нужен какой-то способ для захвата и обработки различных входных данных. Вы делаете это с помощью системы событийpygame.

Обработка событий

Нажатие клавиш, движения мыши и даже движения джойстика являются одними из способов, которыми пользователь может обеспечить ввод. Результатом всего пользовательского ввода является созданиеevent. События могут происходить в любое время и часто (но не всегда) происходят вне программы. Все события вpygame помещаются в очередь событий, к которой затем можно получить доступ и управлять ими. Работа с событиями обозначаетсяhandling них, а код для этого называетсяevent handler.

Каждое событие вpygame имеет связанное с ним событиеtype. Для вашей игры типы событий, на которых вы сосредоточитесь, — это нажатия клавиш и закрытие окна. События нажатия клавиш имеют тип событияKEYDOWN, а событие закрытия окна имеет типQUIT. Различные типы событий могут также иметь другие данные, связанные с ними. Например, тип событияKEYDOWN также имеет переменную с именемkey, чтобы указать, какая клавиша была нажата.

Вы получаете доступ к списку всех активных событий в очереди, вызываяpygame.event.get(). Затем вы просматриваете этот список, проверяете каждый тип события и отвечаете соответственно:

27 # Variable to keep the main loop running
28 running = True
29
30 # Main loop
31 while running:
32     # Look at every event in the queue
33     for event in pygame.event.get():
34         # Did the user hit a key?
35         if event.type == KEYDOWN:
36             # Was it the Escape key? If so, stop the loop.
37             if event.key == K_ESCAPE:
38                 running = False
39
40         # Did the user click the window close button? If so, stop the loop.
41         elif event.type == QUIT:
42             running = False

Давайте внимательнее посмотрим на этот игровой цикл:

  • Line 28 устанавливает управляющую переменную для игрового цикла. Чтобы выйти из цикла и игры, вы устанавливаетеrunning = False. Игровой цикл начинается в строке 29.

  • Line 31 запускает обработчик событий, просматривая все события в очереди событий. Если событий нет, список пуст, и обработчик ничего не сделает.

  • Lines 35 to 38 проверяет, является ли текущийevent.type событиемKEYDOWN. Если это так, то программа проверяет, какая клавиша была нажата, глядя на атрибутevent.key. Если ключ является ключом[.kbd .key-escape]#Esc #, обозначеннымK_ESCAPE, то он выходит из игрового цикла, устанавливаяrunning = False.

  • Lines 41 and 42 выполняет аналогичную проверку для типа события с именемQUIT. Это событие происходит только тогда, когда пользователь нажимает кнопку закрытия окна. Пользователь также может использовать любое другое действие операционной системы, чтобы закрыть окно.

Когда вы добавите эти строки в предыдущий код и запустите его, вы увидите окно с пустым или черным экраном:

An empty

Окно не исчезнет, ​​пока вы не нажмете клавишу[.kbd .key-escape]#Esc # или иным образом не вызовете событиеQUIT, закрыв окно.

Рисование на экране

В примере программы вы рисовали на экране с помощью двух команд:

  1. screen.fill() для заливки фона

  2. pygame.draw.circle(), чтобы нарисовать круг

Теперь вы узнаете о третьем способе рисования на экране: с помощьюSurface.

Напомним, чтоSurface — это прямоугольный объект, на котором вы можете рисовать, как чистый лист бумаги. Объектscreen — этоSurface, и вы можете создавать свои собственные объектыSurface отдельно от экрана дисплея. Давайте посмотрим, как это работает:

44 # Fill the screen with white
45 screen.fill((255, 255, 255))
46
47 # Create a surface and pass in a tuple containing its length and width
48 surf = pygame.Surface((50, 50))
49
50 # Give the surface a color to separate it from the background
51 surf.fill((0, 0, 0))
52 rect = surf.get_rect()

После заполнения экрана белым цветом в строке 45 создается новыйSurface в строке 48. ЭтотSurface имеет ширину 50 пикселей, высоту 50 пикселей и назначенsurf. На этом этапе вы относитесь к нему так же, как кscreen. Итак, на линии 51 вы заполняете его черным. Вы также можете получить доступ к его базовомуRect, используя.get_rect(). Он сохраняется какrect для дальнейшего использования.

Используя.blit() и.flip()

Просто создать новыйSurface недостаточно, чтобы увидеть его на экране. Для этого вам нужноblitSurface на другойSurface. Терминblit означаетBlock Transfer, а.blit() — это то, как вы копируете содержимое одногоSurface в другой. Вы можете только.blit() от одногоSurface к другому, но поскольку экран — это просто еще одинSurface, это не проблема. Вот как вы рисуетеsurf на экране:

54 # This line says "Draw surf onto the screen at the center"
55 screen.blit(surf, (SCREEN_WIDTH/2, SCREEN_HEIGHT/2))
56 pygame.display.flip()

Вызов.blit() в строке 55 принимает два аргумента:

  1. Surface для рисования

  2. Место для его рисования на источникеSurface

Координаты(SCREEN_WIDTH/2, SCREEN_HEIGHT/2) говорят вашей программе разместитьsurf точно в центре экрана, но это не совсем так:

Blitting a surface onto the screen

Причина, по которой изображение выглядит не по центру, заключается в том, что.blit() помещаетtop-left corner изsurf в указанное место. Если вы хотите, чтобыsurf был центрирован, вам нужно будет выполнить некоторые вычисления, чтобы сместить его вверх и влево. Вы можете сделать это, вычтя ширину и высотуsurf из ширины и высоты экрана, разделив каждую на 2, чтобы определить местонахождение центра, а затем передав эти числа в качестве аргументов вscreen.blit():

54 # Put the center of surf at the center of the display
55 surf_center = (
56     (SCREEN_WIDTH-surf.get_width())/2,
57     (SCREEN_HEIGHT-surf.get_height())/2
58 )
59
60 # Draw surf at the new coordinates
61 screen.blit(surf, surf_center)
62 pygame.display.flip()

Обратите внимание на вызовpygame.display.flip() после вызоваblit(). Это обновляет весь экран со всем, что было нарисовано с момента последнего переворота. Без вызова.flip() ничего не отображается.

Спрайты

В вашем игровом дизайне игрок начинает слева, а справа появляются препятствия. Вы можете представить все препятствия с помощью объектовSurface, чтобы все было проще рисовать, но как узнать, где их нарисовать? Как узнать, столкнулось ли препятствие с игроком? Что происходит, когда препятствие летит за пределы экрана? Что делать, если вы хотите нарисовать фоновые изображения, которые также перемещаются? Что если вы хотите, чтобы ваши изображения были анимированными? Вы можете справиться со всеми этими и другими ситуациями с помощьюsprites.

С точки зрения программированияsprite — это 2D-представление чего-либо на экране. По сути, это картина. pygame предоставляетSprite class, который предназначен для хранения одного или нескольких графических представлений любого игрового объекта, который вы хотите отобразить на экране. Чтобы использовать его, вы создаете новый класс, расширяющийSprite. Это позволяет использовать его встроенные методы.

игроки

Вот как вы используете объектыSprite в текущей игре для определения игрока. Вставьте этот код после строки 18:

20 # Define a Player object by extending pygame.sprite.Sprite
21 # The surface drawn on the screen is now an attribute of 'player'
22 class Player(pygame.sprite.Sprite):
23     def __init__(self):
24         super(Player, self).__init__()
25         self.surf = pygame.Surface((75, 25))
26         self.surf.fill((255, 255, 255))
27         self.rect = self.surf.get_rect()

Сначала вы определяетеPlayer, расширяяpygame.sprite.Sprite в строке 22. Затем.__init__() использует.super() для вызова метода.__init__() дляSprite. Для получения дополнительной информации о том, почему это необходимо, вы можете прочитатьSupercharge Your Classes With Python super().

Затем вы определяете и инициализируете.surf, чтобы удерживать изображение для отображения, которое в настоящее время представляет собой белое поле. Вы также определяете и инициализируете.rect, который вы будете использовать для рисования игрока позже. Чтобы использовать этот новый класс, вам нужно создать новый объект и изменить код для рисования. Разверните блок кода ниже, чтобы увидеть все это вместе:

Запустите этот код. Вы увидите белый прямоугольник примерно в середине экрана:

Basic player sprite being drawn

Как вы думаете, что произойдет, если вы измените строку 59 наscreen.blit(player.surf, player.rect)? Попробуйте и посмотрите:

55 # Fill the screen with black
56 screen.fill((0, 0, 0))
57
58 # Draw the player on the screen
59 screen.blit(player.surf, player.rect)
60
61 # Update the display
62 pygame.display.flip()

Когда вы передаетеRect в.blit(), он использует координаты верхнего левого угла для рисования поверхности. Вы будете использовать это позже, чтобы заставить вашего игрока двигаться!

Пользовательский ввод

До сих пор вы научились настраиватьpygame и рисовать объекты на экране. Теперь начинается самое интересное! Вы сделаете плеер управляемым с помощью клавиатуры.

Ранее вы видели, чтоpygame.event.get() возвращает список событий в очереди событий, которую вы просматриваете на предмет типов событийKEYDOWN. Ну, это не единственный способ читать нажатия клавиш. pygame также предоставляетpygame.event.get_pressed(), который возвращаетdictionary, содержащий все текущие событияKEYDOWN в очереди.

Поместите это в свой игровой цикл сразу после цикла обработки событий. Это возвращает словарь, содержащий клавиши, нажимаемые в начале каждого кадра:

54 # Get the set of keys pressed and check for user input
55 pressed_keys = pygame.key.get_pressed()

Затем вы пишете метод вPlayer для приема этого словаря. Это будет определять поведение спрайта на основе нажатых клавиш. Вот как это может выглядеть:

29 # Move the sprite based on user keypresses
30 def update(self, pressed_keys):
31     if pressed_keys[K_UP]:
32         self.rect.move_ip(0, -5)
33     if pressed_keys[K_DOWN]:
34         self.rect.move_ip(0, 5)
35     if pressed_keys[K_LEFT]:
36         self.rect.move_ip(-5, 0)
37     if pressed_keys[K_RIGHT]:
38         self.rect.move_ip(5, 0)

K_UP,K_DOWN,K_LEFT иK_RIGHT соответствуют клавишам со стрелками на клавиатуре. Если словарная запись для этого ключа —True, значит, этот ключ нажат, и вы перемещаете игрока.rect в правильном направлении. Здесь вы используете.move_ip(), что означаетmove in place, для перемещения текущегоRect.

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

52 # Main loop
53 while running:
54     # for loop through the event queue
55     for event in pygame.event.get():
56         # Check for KEYDOWN event
57         if event.type == KEYDOWN:
58             # If the Esc key is pressed, then exit the main loop
59             if event.key == K_ESCAPE:
60                 running = False
61         # Check for QUIT event. If QUIT, then set running to false.
62         elif event.type == QUIT:
63             running = False
64
65     # Get all the keys currently pressed
66     pressed_keys = pygame.key.get_pressed()
67
68     # Update the player sprite based on user keypresses
69     player.update(pressed_keys)
70
71     # Fill the screen with black
72     screen.fill((0, 0, 0))

Теперь вы можете перемещать прямоугольник игрока по экрану с помощью клавиш со стрелками:

Keypresses moving a sprite in pygame

Вы можете заметить две небольшие проблемы:

  1. Прямоугольник игрока может двигаться очень быстро, если удерживать клавишу нажатой. Вы поработаете над этим позже.

  2. Прямоугольник игрока может сдвинуться с экрана. Давайте решим это сейчас.

Чтобы игрок оставался на экране, вам нужно добавить некоторую логику, чтобы определять, собирается лиrect уйти с экрана. Для этого вы проверяете, не переместились ли координатыrect за пределы экрана. Если это так, то вы даете команду программе переместить ее обратно к краю:

25 # Move the sprite based on user keypresses
26 def update(self, pressed_keys):
27     if pressed_keys[K_UP]:
28         self.rect.move_ip(0, -5)
29     if pressed_keys[K_DOWN]:
30         self.rect.move_ip(0, 5)
31     if pressed_keys[K_LEFT]:
32         self.rect.move_ip(-5, 0)
33     if pressed_keys[K_RIGHT]:
34         self.rect.move_ip(5, 0)
35
36     # Keep player on the screen
37     if self.rect.left < 0:
38         self.rect.left = 0
39     if self.rect.right > SCREEN_WIDTH:
40         self.rect.right = SCREEN_WIDTH
41     if self.rect.top <= 0:
42         self.rect.top = 0
43     if self.rect.bottom >= SCREEN_HEIGHT:
44         self.rect.bottom = SCREEN_HEIGHT

Здесь вместо использования.move() вы просто меняете соответствующие координаты.top,.bottom,.left или.right напрямую. Проверьте это, и вы увидите, что прямоугольник игрока больше не может сдвинуться с экрана.

Теперь давайте добавим несколько врагов!

враги

Что за игра без врагов? Вы будете использовать методы, которые вы уже изучили, чтобы создать базовый класс врагов, а затем создадите множество из них, чтобы ваш игрок избегал их. Сначала импортируйте библиотекуrandom:

 4 # Import random for random numbers
 5 import random

Затем создайте новый класс спрайтов с именемEnemy, следуя тому же шаблону, который вы использовали дляPlayer:

55 # Define the enemy object by extending pygame.sprite.Sprite
56 # The surface you draw on the screen is now an attribute of 'enemy'
57 class Enemy(pygame.sprite.Sprite):
58     def __init__(self):
59         super(Enemy, self).__init__()
60         self.surf = pygame.Surface((20, 10))
61         self.surf.fill((255, 255, 255))
62         self.rect = self.surf.get_rect(
63             center=(
64                 random.randint(SCREEN_WIDTH + 20, SCREEN_WIDTH + 100),
65                 random.randint(0, SCREEN_HEIGHT),
66             )
67         )
68         self.speed = random.randint(5, 20)
69
70     # Move the sprite based on speed
71     # Remove the sprite when it passes the left edge of the screen
72     def update(self):
73         self.rect.move_ip(-self.speed, 0)
74         if self.rect.right < 0:
75             self.kill()

МеждуEnemy иPlayer есть четыре заметных различия:

  1. On lines 62 to 67, вы обновляетеrect, чтобы он был случайным местом вдоль правого края экрана. Центр прямоугольника находится за пределами экрана. Он расположен в некотором месте между 20 и 100 пикселями от правого края и где-то между верхним и нижним краями.

  2. On line 68, вы определяете.speed как случайное число от 5 до 20. Это указывает, как быстро этот враг движется к игроку.

  3. On lines 73 to 76, вы определяете.update(). Это не требует никаких аргументов, поскольку враги двигаются автоматически. Вместо этого.update() перемещает врага в левую часть экрана на.speed, определенное при его создании.

  4. On line 74, вы проверяете, ушел ли противник за пределы экрана. Чтобы убедиться, чтоEnemy полностью за пределами экрана и не исчезнет просто так, пока он все еще виден, вы убедитесь, что правая сторона.rect прошла за левую часть экрана. Когда противник находится за кадром, вы вызываете.kill(), чтобы предотвратить его дальнейшую обработку.

Итак, что делает.kill()? Чтобы понять это, вы должны знать оSprite Groups.

Спрайт группы

Еще один очень полезный класс, который предоставляетpygame, — этоSprite Group. Это объект, содержащий группу объектовSprite. Так зачем его использовать? Разве вы не можете вместо этого просто отслеживать свои объектыSprite в списке? Что ж, вы можете, но преимущество использованияGroup заключается в методах, которые он предоставляет. Эти методы помогают определить, столкнулся ли какой-либоEnemy сPlayer, что значительно упрощает обновление.

Давайте посмотрим, как создавать группы спрайтов. Вы создадите два разных объектаGroup:

  1. ПервыеGroup будут удерживать каждыеSprite в игре.

  2. ВторойGroup будет содержать только объектыEnemy.

Вот как это выглядит в коде:

82 # Create the 'player'
83 player = Player()
84
85 # Create groups to hold enemy sprites and all sprites
86 # - enemies is used for collision detection and position updates
87 # - all_sprites is used for rendering
88 enemies = pygame.sprite.Group()
89 all_sprites = pygame.sprite.Group()
90 all_sprites.add(player)
91
92 # Variable to keep the main loop running
93 running = True

Когда вы вызываете.kill(),Sprite удаляется из каждогоGroup, которому он принадлежит. Это также удаляет ссылки наSprite, что позволяет сборщику мусора Python при необходимости освобождать память.

Теперь, когда у вас есть группаall_sprites, вы можете изменить способ рисования объектов. Вместо вызова.blit() только дляPlayer, вы можете перебирать все вall_sprites:

117 # Fill the screen with black
118 screen.fill((0, 0, 0))
119
120 # Draw all sprites
121 for entity in all_sprites:
122     screen.blit(entity.surf, entity.rect)
123
124 # Flip everything to the display
125 pygame.display.flip()

Теперь все, что помещено вall_sprites, будет отрисовываться с каждым кадром, будь то враг или игрок.

Есть только одна проблема … У тебя нет врагов! Вы можете создать кучу врагов в начале игры, но игра быстро станет скучной, когда все они покинут экран через несколько секунд. Вместо этого давайте рассмотрим, как поддерживать постоянный приток врагов в ходе игры.

Пользовательские события

Дизайн призывает врагов появляться через равные промежутки времени. Это означает, что через заданные интервалы вам нужно сделать две вещи:

  1. Создайте новыйEnemy.

  2. Добавьте его вall_sprites иenemies.

У вас уже есть код, который обрабатывает случайные события. Цикл обработки событий предназначен для поиска случайных событий, происходящих в каждом кадре, и надлежащего обращения с ними. К счастью,pygame не ограничивает вас использованием только тех типов событий, которые он определил. Вы можете определить свои собственные события для обработки по своему усмотрению.

Давайте посмотрим, как создать пользовательское событие, которое генерируется каждые несколько секунд. Вы можете создать собственное событие, назвав его:

78 # Create the screen object
79 # The size is determined by the constant SCREEN_WIDTH and SCREEN_HEIGHT
80 screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
81
82 # Create a custom event for adding a new enemy
83 ADDENEMY = pygame.USEREVENT + 1
84 pygame.time.set_timer(ADDENEMY, 250)
85
86 # Instantiate player. Right now, this is just a rectangle.
87 player = Player()

pygame определяет события внутри как целые числа, поэтому вам нужно определить новое событие с уникальным целым числом. Последнее событиеpygame резервов называетсяUSEREVENT, поэтому определениеADDENEMY = pygame.USEREVENT + 1 в строке 83 гарантирует его уникальность.

Затем вам нужно регулярно вставлять это новое событие в очередь на протяжении всей игры. Вот тут и пригодится модульtime. Строка 84 запускает новое событиеADDENEMY каждые 250 миллисекунд или четыре раза в секунду. Вы вызываете.set_timer() вне игрового цикла, поскольку вам нужен только один таймер, но он будет срабатывать на протяжении всей игры.

Добавьте код для обработки вашего нового события:

100 # Main loop
101 while running:
102     # Look at every event in the queue
103     for event in pygame.event.get():
104         # Did the user hit a key?
105         if event.type == KEYDOWN:
106             # Was it the Escape key? If so, stop the loop.
107             if event.key == K_ESCAPE:
108                 running = False
109
110         # Did the user click the window close button? If so, stop the loop.
111         elif event.type == QUIT:
112             running = False
113
114         # Add a new enemy?
115         elif event.type == ADDENEMY:
116             # Create the new enemy and add it to sprite groups
117             new_enemy = Enemy()
118             enemies.add(new_enemy)
119             all_sprites.add(new_enemy)
120
121     # Get the set of keys pressed and check for user input
122     pressed_keys = pygame.key.get_pressed()
123     player.update(pressed_keys)
124
125     # Update enemy position
126     enemies.update()

Каждый раз, когда обработчик событий видит новое событиеADDENEMY в строке 115, он создаетEnemy и добавляет его кenemies иall_sprites. ПосколькуEnemy находится вall_sprites, он будет отрисовываться каждый кадр. Вам также необходимо вызватьenemies.update() в строке 126, который обновляет все вenemies, чтобы убедиться, что они перемещаются правильно:

Enemies flying by in pygame

Однако это не единственная причина, по которой существует группа только дляenemies.

Обнаружение столкновений

Ваш игровой дизайн требует, чтобы игра заканчивалась всякий раз, когда враг сталкивается с игроком. Проверка на наличие столкновений является основной техникой программирования игры и обычно требует некоторой нетривиальной математики, чтобы определить, будут ли два спрайта перекрывать друг друга.

Здесь пригодится фреймворк вродеpygame! Написание кода обнаружения столкновений утомительно, ноpygame имеет МНОГОcollision detection methods, доступное для использования.

В этом руководстве вы будете использовать метод под названием.spritecollideany(), который читается как «спрайт сталкивается с любым». Этот метод принимает в качестве параметровSprite иGroup. Он просматривает каждый объект вGroup и проверяет, пересекается ли его.rect с.rectSprite. Если да, то возвращаетсяTrue. В противном случае возвращаетсяFalse. Это идеально подходит для этой игры, поскольку вам нужно проверить, не сталкивается ли отдельныйplayer с одним изGroup изenemies.

Вот как это выглядит в коде:

130 # Draw all sprites
131 for entity in all_sprites:
132     screen.blit(entity.surf, entity.rect)
133
134 # Check if any enemies have collided with the player
135 if pygame.sprite.spritecollideany(player, enemies):
136     # If so, then remove the player and stop the loop
137     player.kill()
138     running = False

Строка 135 проверяет, столкнулся лиplayer с каким-либо из объектов вenemies. Если это так, то вызываетсяplayer.kill(), чтобы удалить его из каждой группы, к которой он принадлежит. Поскольку визуализируются только объекты вall_sprites,player больше не будет отображаться. После того, как игрок был убит, вам также необходимо выйти из игры, поэтому вы устанавливаетеrunning = False для выхода из игрового цикла в строке 138.

Теперь у вас есть основные элементы игры:

Pygame window

Теперь давайте немного нарядим его, сделаем его более играбельным и добавим некоторые расширенные возможности, которые помогут ему выделиться.

Спрайт Изображения

Хорошо, у вас есть игра, но давайте будем честными … Это некрасиво. Игрок и враги — это просто белые блоки на черном фоне. КогдаPong был новым, это было по последнему слову техники, но он больше не работает. Давайте заменим все эти скучные белые прямоугольники более прохладными изображениями, которые сделают игру настоящей игрой.

Ранее вы узнали, что изображения на диске могут быть загружены вSurface с некоторой помощью модуляimage. Для этого урока мы сделали небольшую струю для игрока и несколько ракет для врагов. Вы можете использовать этот рисунок, нарисовать свой собственный или загрузить несколькоfree game art assets для использования. Вы можете нажать на ссылку ниже, чтобы загрузить искусство, используемое в этом руководстве:

Изменение конструкторов объектов

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

 7 # Import pygame.locals for easier access to key coordinates
 8 # Updated to conform to flake8 and black standards
 9 # from pygame.locals import *
10 from pygame.locals import (
11     RLEACCEL,
12     K_UP,
13     K_DOWN,
14     K_LEFT,
15     K_RIGHT,
16     K_ESCAPE,
17     KEYDOWN,
18     QUIT,
19 )
20
21 # Define constants for the screen width and height
22 SCREEN_WIDTH = 800
23 SCREEN_HEIGHT = 600
24
25
26 # Define the Player object by extending pygame.sprite.Sprite
27 # Instead of a surface, use an image for a better-looking sprite
28 class Player(pygame.sprite.Sprite):
29     def __init__(self):
30         super(Player, self).__init__()
31         self.image = pygame.image.load("jet.png").convert()
32         self.image.set_colorkey((255, 255, 255), RLEACCEL)
33         self.rect = self.image.get_rect()

Давайте немного распакуем строку 31. pygame.image.load() загружает образ с диска. Вы передаете ему путь к файлу. Он возвращаетSurface, а вызов.convert() оптимизируетSurface, ускоряя будущие вызовы.blit().

В строке 32 используется.set_colorkey(), чтобы указать, что цветpygame будет отображаться как прозрачный. В этом случае вы выбираете белый, потому что это цвет фона изображения струи. КонстантаRLEACCEL — это необязательный параметр, который помогает быстрее отображатьpygame на дисплеях без ускорения. Это добавляется к оператору импортаpygame.locals в строке 11.

Больше ничего не нужно менять. Изображение по-прежнемуSurface, только теперь на нем нарисовано изображение. Вы все еще используете его таким же образом.

Вот как выглядят похожие изменения вEnemy:

59 # Define the enemy object by extending pygame.sprite.Sprite
60 # Instead of a surface, use an image for a better-looking sprite
61 class Enemy(pygame.sprite.Sprite):
62     def __init__(self):
63         super(Enemy, self).__init__()
64         self.surf = pygame.image.load("missile.png").convert()
65         self.surf.set_colorkey((255, 255, 255), RLEACCEL)
66         # The starting position is randomly generated, as is the speed
67         self.rect = self.surf.get_rect(
68             center=(
69                 random.randint(SCREEN_WIDTH + 20, SCREEN_WIDTH + 100),
70                 random.randint(0, SCREEN_HEIGHT),
71             )
72         )
73         self.speed = random.randint(5, 20)

Запуск программы сейчас должен показать, что это та же игра, что и у вас раньше, только теперь вы добавили красивую графикуskins с изображениями. Но зачем останавливаться на том, чтобы заставить игрока и вражеских спрайтов выглядеть красиво? Давайте добавим несколько облаков, проходящих мимо, чтобы создать впечатление струи, летящей по небу.

Добавление фоновых изображений

Для фоновых облаков вы используете те же принципы, что и дляPlayer иEnemy:

  1. Создайте классCloud.

  2. Добавьте к нему изображение облака.

  3. Создайте метод.update(), который перемещаетcloud в левую часть экрана.

  4. Создайте настраиваемое событие и обработчик для создания новых объектовcloud через заданный интервал времени.

  5. Добавьте вновь созданные объектыcloud в новыйGroup с именемclouds.

  6. Обновите и нарисуйтеclouds в своем игровом цикле.

Вот как выглядитCloud:

 83 # Define the cloud object by extending pygame.sprite.Sprite
 84 # Use an image for a better-looking sprite
 85 class Cloud(pygame.sprite.Sprite):
 86     def __init__(self):
 87         super(Cloud, self).__init__()
 88         self.surf = pygame.image.load("cloud.png").convert()
 89         self.surf.set_colorkey((0, 0, 0), RLEACCEL)
 90         # The starting position is randomly generated
 91         self.rect = self.surf.get_rect(
 92             center=(
 93                 random.randint(SCREEN_WIDTH + 20, SCREEN_WIDTH + 100),
 94                 random.randint(0, SCREEN_HEIGHT),
 95             )
 96
 97     # Move the cloud based on a constant speed
 98     # Remove the cloud when it passes the left edge of the screen
 99     def update(self):
100         self.rect.move_ip(-5, 0)
101         if self.rect.right < 0:
102             self.kill()

Это все должно выглядеть очень знакомым. Это почти то же самое, что иEnemy.

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

116 # Create custom events for adding a new enemy and a cloud
117 ADDENEMY = pygame.USEREVENT + 1
118 pygame.time.set_timer(ADDENEMY, 250)
119 ADDCLOUD = pygame.USEREVENT + 2
120 pygame.time.set_timer(ADDCLOUD, 1000)

Это говорит о том, что нужно подождать 1000 миллисекунд или одну секунду перед созданием следующегоcloud.

Затем создайте новыйGroup для хранения каждого вновь созданногоcloud:

125 # Create groups to hold enemy sprites, cloud sprites, and all sprites
126 # - enemies is used for collision detection and position updates
127 # - clouds is used for position updates
128 # - all_sprites is used for rendering
129 enemies = pygame.sprite.Group()
130 clouds = pygame.sprite.Group()
131 all_sprites = pygame.sprite.Group()
132 all_sprites.add(player)

Затем добавьте обработчик для нового событияADDCLOUD в обработчике событий:

137 # Main loop
138 while running:
139     # Look at every event in the queue
140     for event in pygame.event.get():
141         # Did the user hit a key?
142         if event.type == KEYDOWN:
143             # Was it the Escape key? If so, then stop the loop.
144             if event.key == K_ESCAPE:
145                 running = False
146
147         # Did the user click the window close button? If so, stop the loop.
148         elif event.type == QUIT:
149             running = False
150
151         # Add a new enemy?
152         elif event.type == ADDENEMY:
153             # Create the new enemy and add it to sprite groups
154             new_enemy = Enemy()
155             enemies.add(new_enemy)
156             all_sprites.add(new_enemy)
157
158         # Add a new cloud?
159         elif event.type == ADDCLOUD:
160             # Create the new cloud and add it to sprite groups
161             new_cloud = Cloud()
162             clouds.add(new_cloud)
163             all_sprites.add(new_cloud)

Наконец, убедитесь, чтоclouds обновляются каждый кадр:

167 # Update the position of enemies and clouds
168 enemies.update()
169 clouds.update()
170
171 # Fill the screen with sky blue
172 screen.fill((135, 206, 250))

Строка 172 обновляет исходныйscreen.fill(), чтобы заполнить экран приятным небесно-голубым цветом. Вы можете изменить этот цвет на что-то другое. Может быть, вы хотите инопланетный мир с пурпурным небом, ядовитую пустошь в неоново-зеленом или поверхность Марса в красном!

Обратите внимание, что каждый новыйCloud иEnemy добавляется кall_sprites, а также кclouds иenemies. Это сделано потому, что каждая группа используется для отдельной цели:

  • Rendering выполняется с использованиемall_sprites.

  • Position updates выполняется с использованиемclouds иenemies.

  • Collision detection выполняется с использованиемenemies.

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

Скорость игры

Во время тестирования игры вы могли заметить, что враги двигаются немного быстро. Если нет, то это нормально, так как разные машины будут видеть разные результаты на этом этапе.

Причина этого в том, что игровой цикл обрабатывает кадры настолько быстро, насколько позволяет процессор и среда. Поскольку все спрайты перемещаются один раз за кадр, они могут перемещаться сотни раз в секунду. Количество кадров, обрабатываемых каждую секунду, называетсяframe rate, и правильное определение этого значения — разница между играбельной игрой и той, которую можно забыть.

Как правило, вы хотите максимально высокую частоту кадров, но для этой игры вам нужно немного замедлить ее, чтобы игра стала играбельной. К счастью, модульtime содержитClock, который предназначен именно для этой цели.

ИспользованиеClock для установки воспроизводимой частоты кадров требует всего двух строк кода. Первый создает новыйClock перед началом игрового цикла:

106 # Setup the clock for a decent framerate
107 clock = pygame.time.Clock()

Второй вызывает.tick(), чтобы сообщитьpygame, что программа достигла конца кадра:

188 # Flip everything to the display
189 pygame.display.flip()
190
191 # Ensure program maintains a rate of 30 frames per second
192 clock.tick(30)

Аргумент, переданный.tick(), устанавливает желаемую частоту кадров. Для этого.tick() вычисляет количество миллисекунд, которое должен занять каждый кадр, на основе желаемой частоты кадров. Затем он сравнивает это число с количеством миллисекунд, прошедших с момента последнего вызова.tick(). Если прошло недостаточно времени,.tick() задерживает обработку, чтобы гарантировать, что она никогда не превысит указанную частоту кадров.

Переход на меньшую частоту кадров приведет к увеличению времени в каждом кадре для вычислений, в то время как большая частота кадров обеспечивает более плавный (и, возможно, более быстрый) игровой процесс:

Setting the frame rate in pygame

Поиграйте с этим номером, чтобы увидеть, что вам больше нравится!

Звуковые эффекты

Пока что вы сосредоточены на игровом процессе и визуальных аспектах вашей игры. Теперь давайте рассмотрим, как придать вашей игре слуховой вкус. pygame предоставляетmixer для обработки всех действий, связанных со звуком. Вы будете использовать классы и методы этого модуля для обеспечения фоновой музыки и звуковых эффектов для различных действий.

Названиеmixer относится к тому факту, что модуль смешивает различные звуки в единое целое. Используя подмодульmusic, вы можете передавать отдельные звуковые файлы в различных форматах, таких какMP3,Ogg иMod. Вы также можете использоватьSound для удержания одного звукового эффекта для воспроизведения в форматах Ogg илиuncompressed WAV. Все воспроизведение происходит в фоновом режиме, поэтому, когда вы проигрываетеSound, метод немедленно возвращается по мере воспроизведения звука.

Note:pygame documentation указывает, что поддержка MP3 ограничена, а неподдерживаемые форматы могут вызвать сбои системы. Звуки, упомянутые в этой статье, были протестированы, и мы рекомендуем тщательно протестировать любые звуки перед выпуском вашей игры.

Как и в большинстве случаевpygame, использованиеmixer начинается с этапа инициализации. К счастью, этим уже занимаетсяpygame.init(). Вам нужно только вызватьpygame.mixer.init(), если вы хотите изменить значения по умолчанию:

106 # Setup for sounds. Defaults are good.
107 pygame.mixer.init()
108
109 # Initialize pygame
110 pygame.init()
111
112 # Set up the clock for a decent framerate
113 clock = pygame.time.Clock()

pygame.mixer.init() принимаетa number of arguments, но в большинстве случаев значения по умолчанию работают нормально. Обратите внимание: если вы хотите изменить значения по умолчанию, вам нужно вызватьpygame.mixer.init() перед вызовомpygame.init(). В противном случае значения по умолчанию будут действовать независимо от ваших изменений.

После инициализации системы вы можете настроить свои звуки и фоновую музыку:

135 # Load and play background music
136 # Sound source: http://ccmixter.org/files/Apoxode/59262
137 # License: https://creativecommons.org/licenses/by/3.0/
138 pygame.mixer.music.load("Apoxode_-_Electric_1.mp3")
139 pygame.mixer.music.play(loops=-1)
140
141 # Load all sound files
142 # Sound sources: Jon Fincher
143 move_up_sound = pygame.mixer.Sound("Rising_putter.ogg")
144 move_down_sound = pygame.mixer.Sound("Falling_putter.ogg")
145 collision_sound = pygame.mixer.Sound("Collision.ogg")

Lines 138 and 139 загружает фоновый звуковой клип и начинает его воспроизведение. Вы можете указать звуковому клипу зацикливаться и никогда не заканчиваться, задав именованный параметрloops=-1.

Lines 143 to 145 загружает три звука, которые вы будете использовать для различных звуковых эффектов. Первые два — это повышающиеся и понижающиеся звуки, которые воспроизводятся, когда игрок движется вверх или вниз. Последний звук используется всякий раз, когда происходит столкновение. Вы также можете добавить другие звуки, такие как звук, когда создаетсяEnemy, или последний звук, когда игра заканчивается.

Итак, как вы используете звуковые эффекты? Вы хотите воспроизвести каждый звук, когда происходит определенное событие. Например, когда корабль движется вверх, вы хотите сыгратьmove_up_sound. Следовательно, вы добавляете вызов.play() всякий раз, когда обрабатываете это событие. В дизайне это означает добавление следующих вызовов к.update() дляPlayer:

26 # Define the Player object by extending pygame.sprite.Sprite
27 # Instead of a surface, use an image for a better-looking sprite
28 class Player(pygame.sprite.Sprite):
29     def __init__(self):
30         super(Player, self).__init__()
31         self.surf = pygame.image.load("jet.png").convert()
32         self.surf.set_colorkey((255, 255, 255), RLEACCEL)
33         self.rect = self.surf.get_rect()
34
35     # Move the sprite based on keypresses
36     def update(self, pressed_keys):
37         if pressed_keys[K_UP]:
38             self.rect.move_ip(0, -5)
39             move_up_sound.play()
40         if pressed_keys[K_DOWN]:
41             self.rect.move_ip(0, 5)
42             move_down_sound.play()

Для столкновения между игроком и врагом вы воспроизводите звук, когда обнаруживаются столкновения:

201 # Check if any enemies have collided with the player
202 if pygame.sprite.spritecollideany(player, enemies):
203     # If so, then remove the player
204     player.kill()
205
206     # Stop any moving sounds and play the collision sound
207     move_up_sound.stop()
208     move_down_sound.stop()
209     collision_sound.play()
210
211     # Stop the loop
212     running = False

Здесь вы сначала останавливаете любые другие звуковые эффекты, потому что при столкновении игрок больше не движется. Затем вы проигрываете звук столкновения и продолжаете исполнение оттуда.

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

220 # All done! Stop and quit the mixer.
221 pygame.mixer.music.stop()
222 pygame.mixer.quit()

Технически эти последние несколько строк не требуются, так как программа заканчивается сразу после этого. Однако если позже вы решите добавить в игру вводный экран или экран выхода, то после завершения игры может появиться больше кода.

Это оно! Проверьте это снова, и вы должны увидеть что-то вроде этого:

Pygame window

Примечание к источникам

Возможно, вы заметили комментарий в строках 136-137 при загрузке фоновой музыки, в котором указан источник музыки и ссылка на лицензию Creative Commons. Это было сделано, потому что создатель этого звука требовал этого. В лицензионных требованиях указывалось, что для использования звука необходимо предоставить как надлежащую атрибуцию, так и ссылку на лицензию.

Вот некоторые источники музыки, звука и искусства, которые вы можете найти для полезного контента:

  • OpenGameArt.org: звуки, звуковые эффекты, спрайты и другие изображения

  • Kenney.nl: звуки, звуковые эффекты, спрайты и другие изображения

  • Gamer Art 2D: спрайты и другие изображения

  • CC Mixter: звуки и звуковые эффекты

  • Freesound: звуки и звуковые эффекты

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

Заключение

Из этого руководства вы узнали, чем программирование игр с помощьюpygame отличается от стандартного процедурного программирования. Вы также узнали, как:

  • Реализация циклов событий

  • Рисовать предметы на экране

  • Воспроизведение звуковых эффектов и музыки

  • Обрабатывать пользовательский ввод

Для этого вы использовали подмножество модулейpygame, включаяdisplay,mixer иmusic,time,image,event и модулиkey. Вы также использовали несколько классовpygame, включаяRect,Surface,Sound иSprite. Но это лишь малая часть того, на что способенpygame! Посмотритеofficial pygame documentation для получения полного списка доступных модулей и классов.

Вы можете найти весь код, графику и звуковые файлы для этой статьи, нажав на ссылку ниже:

Не стесняйтесь оставлять комментарии ниже. Счастливого Pythoning!

#статьи

  • 15 июл 2022

  • 0

Учимся программировать через разработку игр. Сегодня напишем знакомую всем «Змейку» — вспомним правила игры и реализуем их на Python.

Иллюстрация: Оля Ежак для Skillbox Media

Антон Яценко

Изучает Python, его библиотеки и занимается анализом данных. Любит путешествовать в горах.

Pygame — популярная библиотека для создания игр под различные устройства на Windows, macOS, Linux или Android. Она помогает разработчику не только описать геймплей, но и работать с клавиатурой, мышью, акселерометром, звуком и видео.

Первая версия Pygame была представлена Питом Шиннерсом в октябре 2000 года. За 22 года вокруг библиотеки сложилось большое комьюнити, а о работе с ней написано несколько десятков книг. Последняя стабильная версия на июль 2022 года — 2.1.2.

Давайте разберёмся в том, как устроена Pygame, и напишем свою первую игру — классическую «Змейку» на Python, которую студенты часто берут для курсовой работы по программированию.

Pygame — не самостоятельная библиотека. На самом деле это обёртка для библиотеки SDL, Simple DirectMedia Layer. Именно SDL позволяет задействовать любые внешние устройства — например, мышь или клавиатуру. А Pygame делает работу с ними удобной для Python-разработчика.

Установить Pygame просто. Для этого воспользуемся терминалом или командной строкой и командой pip:

pip install pygame

Если во время установки возникают ошибки, то можно воспользоваться официальной документацией. В ней описаны особенности установки на различные системы, а также пути решения распространённых проблем.

Библиотека Pygame состоит из конструкций на языке Python и включает в себя несколько модулей. Модули позволяют получить доступ к определённому устройству и содержат методы для работы с ним. Например, модуль display позволяет работать с экраном, а joystick — считывать движения с джойстика.

После того как вы импортировали Pygame, необходимо инициировать библиотеку с помощью команды pygame.int(). Это поможет нам использовать любые методы любых функций, включённых в библиотеку модулей. Без инициализации код может потерять кросс-платформенность и не запускаться в другой системе.

Помимо модулей, Pygame включает несколько классов Python, которые работают с концепциями, не зависящими от аппаратного обеспечения. Одна из таких концепций — Surface. Surface, можно сказать, определяет прямоугольную область, на которой можно рисовать. Если переносить на практику, то этот класс позволяет создать игровое поле. Он широко используется при работе с Pygame, и мы тоже поработаем с ним при создании «Змейки».

В Pygame вся информация выводится на игровое поле, которому в коде соответствует класс display. Игровое поле может быть полноэкранным или занимать часть экрана. Display создаётся с помощью функции .set_mode(), которая возвращает Surface, представляющий видимую часть окна. Именно эту область вы будете передавать в функции рисования, такие как pygame.draw.circle(), а содержимое этого Surface будет выводиться на дисплей при вызове pygame.display.flip(). Звучит сложно, но на практике будет проще. Оба класса мы будем использовать при создании «Змейки».

Работать с изображениями в Pygame можно двумя способами: создавать их с нуля на экране или использовать изображения с диска. И тот и другой тип можно перезаписывать, загружать и сохранять в различных форматах — например, в PNG и JPG.

Изображения — не самостоятельные компоненты: они загружаются в объекты Surface, которые можно изменять и выводить на дисплеи различными способами.

Выше мы писали, что объекты Surface представлены прямоугольниками, подобно многим другим объектам в Pygame, в том числе изображениям и окнам. Прямоугольники используются настолько активно, что существует даже специальный класс Rect, предназначенный для работы только с ними. Объекты Rect используются для различных задач: создания фигур игрока и врагов, управления взаимодействиями между ними и так далее.

Перед тем как начать писать код, необходимо подумать о том, какие правила мы должны учитывать при создании игры. Давайте составим для «Змейки» базовые правила, которые влияют на геймплей:

  • цель игры — набрать как можно больше очков за счёт увеличения длины змейки:
  • при поглощении специального объекта на игровом экране длина змейки увеличивается на один блок;
  • игрок начинает движение с левой стороны экрана;
  • игрок может двигаться влево, вправо, вверх или вниз;
  • игрок не может двигаться за пределы экрана, при столкновении с границами игра заканчивается;
  • игра заканчивается, когда змейка врезается сама в себя;
  • ещё игра заканчивается, когда пользователь закрывает окно.

Несмотря на то что «Змейка» — простая игра, нам предстоит написать довольно много кода. Мы разбили этапы создания игры на последовательные шаги, каждый из которых реализует отдельную часть геймплея.


Запускаем Python

Писать код на Python лучше всего в специальном редакторе. Есть несколько вариантов:

  • Воспользоваться специализированными IDE: IntelliJ IDEA или Visual Studio Code. Мы рекомендуем именно этот способ — например, весь код для этой статьи мы писали в Visual Studio Code.
  • Использовать терминал на macOS или Linux или воспользоваться командной строкой в Windows. Для этого предварительно потребуется установить Python в систему. Мы подробно писали об этом в отдельном материале.

После установки и запуска Python загружаем библиотеку Pygame:

pip install pygame

Теперь у нас всё готово к работе над игрой. Для дальнейшего написания кода необходимо создать один пустой Python-файл.


Создаём игровое поле

Чтобы создать окно с игрой с помощью Pygame, необходимо использовать функцию display.set_mode() и передать в неё желаемый размер окна в пикселях. Также необходимо использовать методы init() и quit() для инициализации библиотеки в начале кода и её деинициализации в конце кода.

Метод update() используется для обновления содержимого экрана. Существует ещё метод flip(), который работает аналогично update(). Разница в том, что метод update() обновляет только внесённые изменения, а метод flip() перерисовывает экран целиком. Но если в метод update() не передавать никакие параметры, то также обновится весь экран.

import pygame
 
pygame.init()
dis=pygame.display.set_mode((500,400))  #Задаём размер игрового поля.
 
pygame.display.update()
 
pygame.quit()
quit()

Если сейчас запустить этот код, то экран игры сразу же закроется. Это связано с тем, что код сразу переходит к следующей строчке pygame.quit(), отключающей библиотеку и наше игровое поле. Чтобы избежать этого, необходимо воспользоваться циклом while — он не позволит игровому экрану закрыться:

import pygame
 
pygame.init()
 
dis=pygame.display.set_mode((500,400))
pygame.display.update()
pygame.display.set_caption('Змейка от Skillbox') #Добавляем название игры.
 
game_over=False #Создаём переменную, которая поможет нам контролировать 
статус игры — завершена она или нет. Изначально присваиваем значение False,
 то есть игра продолжается.
 
while not game_over:
   for event in pygame.event.get():
       print(event)  #Выводить в терминал все произошедшие события.
 
pygame.quit()
quit()

Кроме этого, мы добавили в код ещё две сущности: название игры и функцию для отслеживания игровых событий. Чтобы у окна с игрой появилось название, мы используем pygame.display.set_caption(») (название пишем в кавычках). А функция event.get() возвращает в терминал все события, которые происходят с игрой.

Запустим код и посмотрим, что получилось:

Скриншот: Pygame / Skillbox Media

Теперь игровое окно не закрывается само по себе. Однако и закрыть его мы тоже не сможем — если нажать на кнопку «Выход», ничего не произойдёт. Исправляем это с помощью кода: добавляем событие QUIT, закрывающее окно.

import pygame
 
pygame.init()
 
dis=pygame.display.set_mode((500, 400))
pygame.display.update()
pygame.display.set_caption('Змейка от Skillbox')
 
game_over=False
while not game_over:
   for event in pygame.event.get():
       if event.type==pygame.QUIT:
           game_over=True
 
pygame.quit()
quit()

Теперь кнопка выхода работает как надо. Если нажать на неё, то окно с игрой закроется.


Создаём змейку

Для начала инициализируем переменные, которые задают цвет. Мы будем использовать их, чтобы присвоить цвет экрану, самой змейке и еде. В Pygame используется стандартная RGB-схема, то есть любой цвет представляет собой комбинацию красного, зелёного и синего цветов, интенсивность которых мы можем менять.

Наша змейка — прямоугольник, поэтому мы воспользуемся функцией создания прямоугольников draw.rect(). Она позволяет задать размер и цвет прямоугольника.

import pygame
 
pygame.init()
 
dis=pygame.display.set_mode((500, 400))
pygame.display.update()
pygame.display.set_caption('Змейка от Skillbox')
 
game_over=False
while not game_over:
   for event in pygame.event.get():
       if event.type==pygame.QUIT:
           game_over=True
 
pygame.quit()
quit()

Запустим код и посмотрим на результат.

Скриншот: Pygame / Skillbox Media

Всё получилось. Ближе к центру экрана появился синий квадрат, который и будет нашей змейкой.


Описываем движения змейки

Управлять перемещением змейки можно с помощью специального класса Pygame KEYDOWN. Класс позволяет использовать четыре стандартных события, получая их с клавиавтуры: K_UP, K_DOWN, K_LEFT и K_RIGHT — они соответствуют движениям змейки вверх, вниз, влево и вправо. Срабатывание любого события из класса KEYDOWN приводит к изменению положения змейки. Зададим шаг этого движения в 10 пикселей.

Кроме того, мы должны создать две переменные для хранения значений координат первой клетки нашей змейки по осям x и y. Назовём их x1_change и y1_change.

import pygame
 
pygame.init()
 
white = (255, 255, 255)
black = (0, 0, 0)
red = (255, 0, 0)
 
dis = pygame.display.set_mode((800, 600))
pygame.display.set_caption('Змейка от Skillbox')
 
game_over = False
x1 = 300 #Указываем начальное значение положения змейки по оси х.
y1 = 300 #Указываем начальное значение положения змейки по оси y.
x1_change = 0 #Создаём переменную, которой в цикле while будут
присваиваться значения изменения положения змейки по оси х.
y1_change = 0 #создаём переменную, которой в цикле while будут
присваиваться значения изменения положения змейки по оси y.
clock = pygame.time.Clock()
 
while not game_over:
   for event in pygame.event.get():
       if event.type == pygame.QUIT:
           game_over = True
       if event.type == pygame.KEYDOWN: #Добавляем считывание направления
движений с клавиатуры.
           if event.key == pygame.K_LEFT:
               x1_change = -10 #Указываем шаг изменения положения змейки
в 10 пикселей.
               y1_change = 0
           elif event.key == pygame.K_RIGHT:
               x1_change = 10
               y1_change = 0
           elif event.key == pygame.K_UP:
               y1_change = -10
               x1_change = 0
           elif event.key == pygame.K_DOWN:
               y1_change = 10
               x1_change = 0
   x1 += x1_change #Записываем новое значение положения змейки по оси х.
   y1 += y1_change #Записываем новое значение положения змейки по оси y.
   dis.fill(white)
   
   pygame.draw.rect(dis, black, [x1, y1, 10, 10])
   pygame.display.update()
   clock.tick(30)
 
pygame.quit()
quit()

Теперь змейка двигается по игровому полю:

Скриншот: Pygame / Skillbox Media

Учитываем препятствия — границы игрового поля

Если змейка попадает на границу экрана, то игрок терпит поражение, а игра заканчивается. Чтобы закодить это правило, можно воспользоваться оператором if, который определяет координаты x и y для змейки и анализирует, выходят ли они за границы игрового поля. Добавим необходимый код.

import pygame
import time
 
pygame.init()
 
white = (255, 255, 255)
black = (0, 0, 0)
red = (255, 0, 0)
 
dis_width = 800 #Зададим размер игрового поля через две переменные.
dis_height = 600
dis = pygame.display.set_mode((dis_width, dis_width))
pygame.display.set_caption('Змейка от Skillbox')
 
game_over = False
x1 = dis_width/2 #Стартовое положение змейки по осям рассчитывается
через переменные, указывающие размер игрового экрана.
y1 = dis_height/2
snake_block=10 #Укажем в переменной стандартную величину сдвига
положения змейки при нажатии на клавиши.
x1_change = 0
y1_change = 0
 
clock = pygame.time.Clock()
snake_speed=15 #Ограничим скорость движения змейки.
font_style = pygame.font.SysFont(None, 50)
 
def message(msg,color): #Создадим функцию, которая будет показывать
нам сообщения на игровом экране.
   mesg = font_style.render(msg, True, color)
   dis.blit(mesg, [dis_width/2, dis_height/2])
 
while not game_over:
   for event in pygame.event.get():
       if event.type == pygame.QUIT:
           game_over = True
       if event.type == pygame.KEYDOWN:
           if event.key == pygame.K_LEFT:
               x1_change = -snake_block
               y1_change = 0
           elif event.key == pygame.K_RIGHT:
               x1_change = snake_block
               y1_change = 0
           elif event.key == pygame.K_UP:
               y1_change = -snake_block
               x1_change = 0
           elif event.key == pygame.K_DOWN:
               y1_change = snake_block
               x1_change = 0
   
  if x1 >= dis_width or x1 < 0 or y1 >= dis_height or y1 < 0:
       game_over = True #Явно укажем, что если координаты змейки
выходят за рамки игрового поля, то игра должна закончиться.
   x1 += x1_change
   y1 += y1_change
   dis.fill(white)
   
   pygame.draw.rect(dis, black, [x1, y1, snake_block, snake_block])
   pygame.display.update()
   clock.tick(snake_speed)
 
message("Вы проиграли :(",red) #Сообщение, которое появляется при
проигрыше. В нашем случае — при выходе змейки за пределы игрового поля.
 
pygame.display.update()
time.sleep(2)
pygame.quit()
 
quit()

Теперь, если змейка достигнет края экрана, игра закончится, а на дисплее появится сообщение о проигрыше:

Скриншот: Pygame / Skillbox Media

Добавляем еду для змейки

Теперь добавим «еду». Используем библиотеку random, чтобы она появлялась в случайном месте на игровом поле. Когда наша змейка будет проходить через еду, то её длина будет увеличиваться. Это мы добавим на следующем шаге. Кроме того, дадим возможность игроку выйти из игры или начать игру заново после проигрыша.

import pygame
import time
import random
 
pygame.init()
white = (255, 255, 255)
black = (0, 0, 0)
red = (255, 0, 0)
blue = (0, 0, 255)
dis_width = 800
dis_height = 600
dis = pygame.display.set_mode((dis_width, dis_height))
pygame.display.set_caption('Змейка от Skillbox')
clock = pygame.time.Clock()
snake_block = 10
snake_speed = 15
font_style = pygame.font.SysFont(None, 30)
 
def message(msg, color):
   mesg = font_style.render(msg, True, color)
   dis.blit(mesg, [dis_width/10, dis_height/3])
 
def gameLoop(): #Описываем всю игровую логику в одной функции.
   game_over = False
   game_close = False
   x1 = dis_width / 2
   y1 = dis_height / 2
   x1_change = 0
   y1_change = 0
   foodx = round(random.randrange(0, dis_width - snake_block) / 10.0) * 10.0 
#Создаём переменную, которая будет указывать расположение еды по оси х.
   foody = round(random.randrange(0, dis_width - snake_block) / 10.0) * 10.0 
#Создаём переменную, которая будет указывать расположение еды по оси y.
   while not game_over:
       while game_close == True:
           dis.fill(white)
           message("Вы проиграли! Нажмите Q для выхода 
или C для повторной игры", red)
           pygame.display.update()
           for event in pygame.event.get():
               if event.type == pygame.KEYDOWN:
                   if event.key == pygame.K_q:
                       game_over = True
                       game_close = False
                   if event.key == pygame.K_c:
                       gameLoop()
       for event in pygame.event.get():
           if event.type == pygame.QUIT:
               game_over = True
           if event.type == pygame.KEYDOWN:
               if event.key == pygame.K_LEFT:
                   x1_change = -snake_block
                   y1_change = 0
               elif event.key == pygame.K_RIGHT:
                   x1_change = snake_block
                   y1_change = 0
               elif event.key == pygame.K_UP:
                   y1_change = -snake_block
                   x1_change = 0
               elif event.key == pygame.K_DOWN:
                   y1_change = snake_block
                   x1_change = 0
       if x1 >= dis_width or x1 < 0 or y1 >= dis_height or y1 < 0:
           game_close = True
       x1 += x1_change
       y1 += y1_change
       dis.fill(white)
       pygame.draw.rect(dis, blue, [foodx, foody, snake_block, snake_block])
       pygame.draw.rect(dis, black, [x1, y1, snake_block, snake_block])
       pygame.display.update()
   
   pygame.quit()
   quit()
 
gameLoop()

Теперь при запуске игры кроме самой змейки будет показана еда. В нашем случае — в виде чёрного квадрата.

Скриншот: Pygame / Skillbox Media

А если выполнить условие для завершения игры, то появится сообщение с предложением выйти из игры или начать её заново:

Скриншот: Pygame / Skillbox Media

Увеличиваем длину змейки

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

import pygame
import time
import random
 
pygame.init()
 
white = (255, 255, 255)
yellow = (255, 255, 102)
black = (0, 0, 0)
red = (213, 50, 80)
green = (0, 255, 0)
blue = (50, 153, 213)
 
dis_width = 800
dis_height = 600
dis = pygame.display.set_mode((dis_width, dis_height))
pygame.display.set_caption('Змейка от Skillbox')
clock = pygame.time.Clock()
snake_block = 10
snake_speed = 15
font_style = pygame.font.SysFont("bahnschrift", 25) #Укажем название
 шрифта и его размер для системных сообщений, например, при завершении игры.
score_font = pygame.font.SysFont("comicsansms", 35) #Укажем шрифт и 
его размер для отображения счёта. Это мы реализуем очень скоро.
 
def our_snake(snake_block, snake_list):
   for x in snake_list:
       pygame.draw.rect(dis, black, [x[0], x[1], snake_block, snake_block])
 
def message(msg, color):
   mesg = font_style.render(msg, True, color)
   dis.blit(mesg, [dis_width / 6, dis_height / 3])
 
 
def gameLoop():
   game_over = False
   game_close = False
   x1 = dis_width / 2
   y1 = dis_height / 2
   x1_change = 0
   y1_change = 0
   snake_List = [] #Создаём список, в котором будем хранить 
показатель текущей длины змейки.
   Length_of_snake = 1 
   foodx = round(random.randrange(0, dis_width - snake_block) / 10.0) * 10.0
   foody = round(random.randrange(0, dis_height - snake_block) / 10.0) * 10.0
   while not game_over:
       while game_close == True:
           dis.fill(blue)
           message("Вы проиграли! Нажмите Q для выхода 
или C для повторной игры", red)
           pygame.display.update()
           for event in pygame.event.get():
               if event.type == pygame.KEYDOWN:
                   if event.key == pygame.K_q:
                       game_over = True
                       game_close = False
                   if event.key == pygame.K_c:
                       gameLoop()
       for event in pygame.event.get():
           if event.type == pygame.QUIT:
               game_over = True
           if event.type == pygame.KEYDOWN:
               if event.key == pygame.K_LEFT:
                   x1_change = -snake_block
                   y1_change = 0
               elif event.key == pygame.K_RIGHT:
                   x1_change = snake_block
                   y1_change = 0
               elif event.key == pygame.K_UP:
                   y1_change = -snake_block
                   x1_change = 0
               elif event.key == pygame.K_DOWN:
                   y1_change = snake_block
                   x1_change = 0
       if x1 >= dis_width or x1 < 0 or y1 >= dis_height or y1 < 0:
           game_close = True
       x1 += x1_change
       y1 += y1_change
       dis.fill(blue)
       pygame.draw.rect(dis, green, [foodx, foody, snake_block, snake_block])
       snake_Head = [] #Создаём список, в котором будет храниться 
показатель длины змейки при движениях.
       snake_Head.append(x1) #Добавляем значения в список при 
изменении по оси х.
       snake_Head.append(y1) #Добавляем значения в список при 
изменении по оси y.
       snake_List.append(snake_Head)
       if len(snake_List) > Length_of_snake:
           del snake_List[0] #Удаляем первый элемент в списке 
длины змейки, чтобы она не увеличивалась сама по себе при движениях.
       for x in snake_List[:-1]:
           if x == snake_Head:
               game_close = True
       our_snake(snake_block, snake_List)
       pygame.display.update()
       if x1 == foodx and y1 == foody: #Указываем, что в случаях, 
если координаты головы змейки совпадают с координатами еды, еда появляется 
в новом месте, а длина змейки увеличивается на одну клетку.
           foodx = round(random.randrange(0, dis_width - snake_block) / 10.0) * 10.0
           foody = round(random.randrange(0, dis_height - snake_block) / 10.0) * 10.0
           Length_of_snake += 1
       clock.tick(snake_speed)
   pygame.quit()
   quit()
 
gameLoop()

Дополнительно мы изменили цвет игрового поля и змейки, увеличив их контрастность.

Скриншот: Pygame / Skillbox Media

Добавляем отображение счёта

Добавим отображение счёта текущей игры. Для этого создадим функцию Your_score. Она будет отображать длину змейки, вычитая из неё 1 (ведь 1 — это начальный размер змейки, и это не является достижением игрока).

def Your_score(score):
   value = score_font.render("Ваш счёт: " + str(score), True, yellow)
   dis.blit(value, [0, 0])

И отдельно пропишем правило определения длины змейки, вычитая из текущей длины змейки единицу.

Your_score(Length_of_snake - 1)

Теперь на игровом поле будет отображаться текущий счёт:

Скриншот: Pygame / Skillbox Media

Можно считать, что наша работа над «Змейкой» закончена. Мы полностью реализовали геймплей, который запланировали на старте работы.

Наш код полностью и без комментариев:

import pygame
import time
import random
pygame.init()
white = (255, 255, 255)
yellow = (255, 255, 102)
black = (0, 0, 0)
red = (213, 50, 80)
green = (0, 255, 0)
blue = (50, 153, 213)
dis_width = 800
dis_height = 600
dis = pygame.display.set_mode((dis_width, dis_height))
pygame.display.set_caption('Змейка от Skillbox')
clock = pygame.time.Clock()
snake_block = 10
snake_speed = 15
font_style = pygame.font.SysFont("bahnschrift", 25)
score_font = pygame.font.SysFont("comicsansms", 35)
 
def Your_score(score):
   value = score_font.render("Ваш счёт: " + str(score), True, yellow)
   dis.blit(value, [0, 0])
 
def our_snake(snake_block, snake_list):
   for x in snake_list:
       pygame.draw.rect(dis, black, [x[0], x[1], snake_block, snake_block])
 
def message(msg, color):
   mesg = font_style.render(msg, True, color)
   dis.blit(mesg, [dis_width / 6, dis_height / 3])
 
def gameLoop():
   game_over = False
   game_close = False
   x1 = dis_width / 2
   y1 = dis_height / 2
   x1_change = 0
   y1_change = 0
   snake_List = []
   Length_of_snake = 1
   foodx = round(random.randrange(0, dis_width - snake_block) / 10.0) * 10.0
   foody = round(random.randrange(0, dis_height - snake_block) / 10.0) * 10.0
   while not game_over:
       while game_close == True:
           dis.fill(blue)
           message("Вы проиграли! Нажмите Q для выхода или C для повторной игры", red)
           Your_score(Length_of_snake - 1)
           pygame.display.update()
           for event in pygame.event.get():
               if event.type == pygame.KEYDOWN:
                   if event.key == pygame.K_q:
                       game_over = True
                       game_close = False
                   if event.key == pygame.K_c:
                       gameLoop()
       for event in pygame.event.get():
           if event.type == pygame.QUIT:
               game_over = True
           if event.type == pygame.KEYDOWN:
               if event.key == pygame.K_LEFT:
                   x1_change = -snake_block
                   y1_change = 0
               elif event.key == pygame.K_RIGHT:
                   x1_change = snake_block
                   y1_change = 0
               elif event.key == pygame.K_UP:
                   y1_change = -snake_block
                   x1_change = 0
               elif event.key == pygame.K_DOWN:
                   y1_change = snake_block
                   x1_change = 0
       if x1 >= dis_width or x1 < 0 or y1 >= dis_height or y1 < 0:
           game_close = True
       x1 += x1_change
       y1 += y1_change
       dis.fill(blue)
       pygame.draw.rect(dis, green, [foodx, foody, snake_block, snake_block])
       snake_Head = []
       snake_Head.append(x1)
       snake_Head.append(y1)
       snake_List.append(snake_Head)
       if len(snake_List) > Length_of_snake:
           del snake_List[0]
       for x in snake_List[:-1]:
           if x == snake_Head:
               game_close = True
       our_snake(snake_block, snake_List)
       Your_score(Length_of_snake - 1)
       pygame.display.update()
       if x1 == foodx and y1 == foody:
           foodx = round(random.randrange(0, dis_width - snake_block) / 10.0) * 10.0
           foody = round(random.randrange(0, dis_height - snake_block) / 10.0) * 10.0
           Length_of_snake += 1
       clock.tick(snake_speed)
   pygame.quit()
   quit()
gameLoop()

Узнать об особенностях работы с Pygame и возможностях библиотеки можно в официальной документации. Углубиться в разработку и попробовать другие игры можно благодаря специализированным книгам:

  • «Учим Python, делая крутые игры» Эла Свейгарта;
  • «Beginning Game Development with Python and Pygame: From Novice to Professional» Уилла Макгугана;
  • «Program Arcade Games: With Python and Pygame» Пола Винсента Крэйвена.

Назад в начало

pygame — это библиотека модулей для языка Python, созданная для разработки 2D игр.

Для того чтобы установить pygame на свой компьютер необходимо открыть командную строку или терминал и написать команду

pip3 install pygame

После установки необходимо создать новый файл и импортировать модуль pygame и написать шаблон игры

# Импортируем библиотеку pygame

import pygame

# Импортируем системную функцию exit

from sys import exit

# Инициализируем pygame

pygame.init()

# Создаем окошко 800 пикселей шириной

# и 600 пикселей высотой и записываем его

# в переменную display.

# Переменную display называют поверхностью.

display = pygame.display.set_mode( (800, 600) )

# Основной цикл игры

while True:

    # Ждем события (действия пользователя)

    for event in pygame.event.get():

        # Если нажали на крестик,

        # то закрываем окно

        if event.type == pygame.QUIT:

            pygame.quit()

            exit()

    # Обновляем поверхность игры

    # на каждом шаге основного цикла игры

    pygame.display.update()

Пользователь может взаимодействовать с нашей игрой. Каждое действие пользователя — это некоторое событие, которое мы можем обработать. Выражение pygame.event.get() — это список событий, произошедших в нашей игре.

Цикл for просто перебирает необработанные события. Каждое событие он присваивает переменной event (можно написать любую другую).

Поговорим о цикле while, основном цикле игры. Как часто он выполняется? Очень и очень часто, это зависит от мощности компьютера. Для обновления экрана в играх часто используют 60 кадров в секунду.

Ограничим количество выполнений цикла.

import pygame

from sys import exit

pygame.init()

display = pygame.display.set_mode( (800, 600) )

FPS = 60 # Создаем переменную FPS

clock = pg.time.Clock() # Создаем счетчик для FPS

while True:

    for event in pygame.event.get():

        if event.type == pygame.QUIT:

            pygame.quit()

            exit()

    pygame.display.update()

    clock.tick(FPS) # Замедляем цикл до 60 выполнений в секунду

Методу tick() передается желаемое количество кадров в секунду. Задержку он вычисляет сам. На каждой итерации основного цикла игры секунда делится на 60 и на вычисленную величину выполняется задержка.

Рисование фигур

В библиотеке pygame существует множество функций для рисования различных фигур.

Функция polygon() рисует произвольную фигуру. Она принимает 3 обязательных параметра (поверхность, цвет и кортеж координат) и 1 необязательный (толщину линий).

import pygame

from sys import exit

pygame.init()

display = pygame.display.set_mode( (800, 600) )

# Рисуем полигон (да, получится квадратик)

pygame.draw.polygon( display, (255, 0, 0) , ( (0, 0), (100, 0), (100, 100), (0, 100) ) )

FPS = 60

clock = pg.time.Clock()

while True:

    for event in pygame.event.get():

        if event.type == pygame.QUIT:

            pygame.quit()

            exit()

    pygame.display.update()

    clock.tick(FPS)

display — наша поверхность

(255, 0, 0) — красный цвет, почитайте про rgb

( (0, 0), (100, 0), (100, 100), (0, 100) ) — координаты вершин квадрата. Возьмите листочек и нарисуйте его координатах (замените сотню на единицу).

Давайте нарисуем треугольник

import pygame

from sys import exit

pygame.init()

display = pygame.display.set_mode( (800, 600) )

# Рисуем квадратик

pygame.draw.polygon( display, (255, 0, 0) , ( (0, 0), (100, 0), (100, 100), (0, 100) ) )

# Рисуем синий треугольник

pygame.draw.polygon( display, (0, 0, 255) , ( (100, 100), (200, 200), (100, 200) ) )

FPS = 60 # Создаем переменную FPS

clock = pg.time.Clock()

while True:

    for event in pygame.event.get():

        if event.type == pygame.QUIT:

            pygame.quit()

            exit()

    pygame.display.update()

    clock.tick(FPS)

display — поверхность

(0, 0, 255) — синий цвет

((100, 100), (200, 200), (100, 200)) — координаты вершин нашего треугольник.

Самостоятельно нарисуйте пятиугольник (вам помогут карандаш и лист бумаги)

Рисование окружностей

Чтобы нарисовать окружность нужно вызвать метод circle из модуля draw. Команда выглядит так: pygame.draw.circle(display, color, position, radius).

display — поверхность, на которой рисуем

color — цвет, записанный в кортеже из трех чисел. (еще раз про rgb)

position — координаты точки центра окружности (кортеж из двух чисел (x, y))

radiusрадиус окружности в пикселях

import pygame

from sys import exit

pygame.init()

display = pygame.display.set_mode( (800, 600) )

# Рисуем квадратик

pygame.draw.polygon( display, (255, 0, 0) , ( (0, 0), (100, 0), (100, 100), (0, 100) ) )

# Рисуем синию линию

pygame.draw.polygon( display, (0, 0, 255) , ( (100, 100), (200, 200), (100, 200) ) )

# Рисуем желтую окружность с радиусом 100 пикселей

pygame.draw.circle( display, (255, 255, 0) , (400,200), 100)

FPS = 60

clock = pg.time.Clock()

while True:

    for event in pygame.event.get():

        if event.type == pygame.QUIT:

            pygame.quit()

            exit()

    pygame.display.update()

    clock.tick(FPS)

display — наша поверхнотсть для рисования

(255, 255, 0) — желтый цвет

(400, 200) — координаты точки центра (в нашем случае 400 пикселей от верхнего левого угла по горизонтали и 200 пикселей по вертикали)

100 — радиус нашей окружности в пикселях

Объявления переменных для цветов

Для нашего с вами удобства давайте объявим несколько переменных, в которые сохраним используемые нами цвета

import pygame

from sys import exit

pygame.init()

WHITE = (255, 255, 255)

BLACK = (0, 0, 0)

PURPLE = (156, 39, 176)

INDIGO = (63, 81, 181)

BLUE = (33, 150, 243)

GREEN = (76, 175, 80)

YELLOW = (255, 235, 59)

ORANGE = (255, 152, 0)

GREY = (158, 158, 158)

display = pygame.display.set_mode( (800, 600) )

# Рисуем квадратик

pygame.draw.polygon( display, (255, 0, 0) , ( (0, 0), (100, 0), (100, 100), (0, 100) ) )

# Рисуем синию линию

pygame.draw.polygon( display, (0, 0, 255) , ( (100, 100), (200, 200), (100, 200) ) )

# Рисуем желтую окружность с радиусом 100 пикселей

pygame.draw.circle( display, (255, 255, 0) , (400,200), 100)

FPS = 60

clock = pg.time.Clock()

while True:

    for event in pygame.event.get():

        if event.type == pygame.QUIT:

            pygame.quit()

            exit()

    pygame.display.update()

    clock.tick(FPS)

Рисование прямоугольников

Для отрисовки прямоугольников можно использовать метод rect.

pygame.draw.rect(display, color, (x, y, width, height) )

colorцвет (теперь можно просто написать имя переменную)

(x, y, width, height) — кортеж из четырех значений. Первые два значения — это координаты верхнего левого угла прямоугольника, а два последних — это ширина и высота.

import pygame

from sys import exit

pygame.init()

WHITE = (255, 255, 255)

BLACK = (0, 0, 0)

PURPLE = (156, 39, 176)

INDIGO = (63, 81, 181)

BLUE = (33, 150, 243)

GREEN = (76, 175, 80)

YELLOW = (255, 235, 59)

ORANGE = (255, 152, 0)

GREY = (158, 158, 158)

display = pygame.display.set_mode( (800, 600) )

# Рисуем квадратик

pygame.draw.polygon( display, (255, 0, 0) , ( (0, 0), (100, 0), (100, 100), (0, 100) ) )

# Рисуем синию линию

pygame.draw.polygon( display, (0, 0, 255) , ( (100, 100), (200, 200), (100, 200) ) )

# Рисуем желтую окружность с радиусом 100 пикселей

pygame.draw.circle( display, (255, 255, 0) , (400,200), 100)

# Рисуем фиолетовый прямоугольник 200х300

pygame.draw.rect( display, PURPLE , (600, 300, 200, 300))

FPS = 60

clock = pg.time.Clock()

while True:

    for event in pygame.event.get():

        if event.type == pygame.QUIT:

            pygame.quit()

            exit()

    pygame.display.update()

    clock.tick(FPS)

Если ваша творческая натура требует большего, то вот ссылка на документацию модулю draw

Там можно найти рисование линий, дуг, эллипсов.

Большой пример (запусти его у себя на компьтере:

import pygame

from sys import exit

from random import randint

# Функция, возвращающая случайный оттенок зеленого цвета

def randomGreen():

    return randint(0, 100), randint(100, 255), randint(0,100)

# Функция, возвращающая случайный оттенок красного цвета

def randomRed():

    return randint(100, 255), randint(0, 100), randint(0,100)

pygame.init()

display = pygame.display.set_mode( (600, 600) )

display.fill((255,255,255))

x = 100 # начальная позиция по оси X

y = 100 # начальная позиция по оси Y

while y < 500: # Пока мы не достигли точки с координатой y == 500

    # Вложенный цикл для рисования линии из квадратиков

    while x < 500: # Пока мы не достигли точки с координатой x == 500

        # Рисуем квадратик с координатами x, y

        pygame.draw.rect(display, randomGreen(), (x, y, 25, 25))

        x += 25 # Смещаем позицию квадратика по оси X

    # По завершению вложенного цикла увеличиваем переменную y

    # для перехода на новую строчку

    y += 25

    x = 100 # Возвращаем позицию по оси X в начало строчки

# Рисуем «мордочку» крипера

pygame.draw.rect(display, (0,0,0), (150, 200, 100, 100))

pygame.draw.rect(display, (0,0,0), (350, 200, 100, 100))

pygame.draw.rect(display, (0,0,0), (250, 300, 100, 100))

pygame.draw.rect(display, (0,0,0), (200, 350, 50, 100))

pygame.draw.rect(display, (0,0,0), (350, 350, 50, 100))

while True:

    for event in pygame.event.get():

        if event.type == pygame.QUIT:

            pygame.quit()

            exit()

    pygame.display.update()

Задания:

1. Нарисуйте дерево из minecraft, используя полученные знания

2. Нарисуйте оранжевую, красную, синию и фиолетовую звезды

pygame


Color

  1. Color
  2. Color.a
  3. Color.b
  4. Color.cmy
  5. Color.correct_gamma
  6. Color.g
  7. Color.hsla
  8. Color.hsva
  9. Color.i1i2i3
  10. Color.lerp
  11. Color.normalize
  12. Color.premul_alpha
  13. Color.r
  14. Color.set_length
  15. Color.update

touch

  1. module-_sdl2.touch
  2. _sdl2.touch.get_device
  3. _sdl2.touch.get_finger
  4. _sdl2.touch.get_num_devices
  5. _sdl2.touch.get_num_fingers

camera

  1. module-camera
  2. camera.Camera
  3. camera.Camera.get_controls
  4. camera.Camera.get_image
  5. camera.Camera.get_raw
  6. camera.Camera.get_size
  7. camera.Camera.query_image
  8. camera.Camera.set_controls
  9. camera.Camera.start
  10. camera.Camera.stop
  11. camera.colorspace
  12. camera.list_cameras

cdrom

  1. module-cdrom
  2. cdrom.CD
  3. cdrom.CD.eject
  4. cdrom.CD.get_all
  5. cdrom.CD.get_busy
  6. cdrom.CD.get_current
  7. cdrom.CD.get_empty
  8. cdrom.CD.get_id
  9. cdrom.CD.get_init
  10. cdrom.CD.get_name
  11. cdrom.CD.get_numtracks
  12. cdrom.CD.get_paused
  13. cdrom.CD.get_track_audio
  14. cdrom.CD.get_track_length
  15. cdrom.CD.get_track_start
  16. cdrom.CD.init
  17. cdrom.CD.pause
  18. cdrom.CD.play
  19. cdrom.CD.quit
  20. cdrom.CD.resume
  21. cdrom.CD.stop
  22. cdrom.get_count
  23. cdrom.get_init
  24. cdrom.init
  25. cdrom.quit

display

  1. module-display
  2. display.Info
  3. display.flip
  4. display.get_active
  5. display.get_allow_screensaver
  6. display.get_caption
  7. display.get_driver
  8. display.get_init
  9. display.get_num_displays
  10. display.get_surface
  11. display.get_window_size
  12. display.get_wm_info
  13. display.gl_get_attribute
  14. display.gl_set_attribute
  15. display.iconify
  16. display.init
  17. display.list_modes
  18. display.mode_ok
  19. display.quit
  20. display.set_allow_screensaver
  21. display.set_caption
  22. display.set_gamma
  23. display.set_gamma_ramp
  24. display.set_icon
  25. display.set_mode
  26. display.set_palette
  27. display.toggle_fullscreen
  28. display.update

draw

  1. module-draw
  2. draw.aaline
  3. draw.aalines
  4. draw.arc
  5. draw.circle
  6. draw.ellipse
  7. draw.line
  8. draw.lines
  9. draw.polygon
  10. draw.rect

event

  1. module-event
  2. event.Event
  3. event.EventType
  4. event.EventType.__dict__
  5. event.EventType.type
  6. event.clear
  7. event.custom_type
  8. event.event_name
  9. event.get
  10. event.get_blocked
  11. event.get_grab
  12. event.peek
  13. event.poll
  14. event.post
  15. event.pump
  16. event.set_allowed
  17. event.set_blocked
  18. event.set_grab
  19. event.wait

examples

  1. module-examples
  2. examples.aliens.main
  3. examples.arraydemo.main
  4. examples.blend_fill.main
  5. examples.blit_blends.main
  6. examples.camera.main
  7. examples.chimp.main
  8. examples.cursors.main
  9. examples.eventlist.main
  10. examples.fastevents.main
  11. examples.fonty.main
  12. examples.freetype_misc.main
  13. examples.glcube.main
  14. examples.headless_no_windows_needed.main
  15. examples.liquid.main
  16. examples.mask.main
  17. examples.midi.main
  18. examples.moveit.main
  19. examples.oldalien.main
  20. examples.overlay.main
  21. examples.pixelarray.main
  22. examples.playmus.main
  23. examples.scaletest.main
  24. examples.scrap_clipboard.main
  25. examples.scroll.main
  26. examples.sound.main
  27. examples.sound_array_demos.main
  28. examples.stars.main
  29. examples.testsprite.main
  30. examples.vgrade.main

fastevent

  1. module-fastevent
  2. fastevent.get
  3. fastevent.get_init
  4. fastevent.init
  5. fastevent.poll
  6. fastevent.post
  7. fastevent.pump
  8. fastevent.wait

font

  1. module-font
  2. font.Font
  3. font.Font.bold
  4. font.Font.get_ascent
  5. font.Font.get_bold
  6. font.Font.get_descent
  7. font.Font.get_height
  8. font.Font.get_italic
  9. font.Font.get_linesize
  10. font.Font.get_underline
  11. font.Font.italic
  12. font.Font.metrics
  13. font.Font.render
  14. font.Font.set_bold
  15. font.Font.set_italic
  16. font.Font.set_underline
  17. font.Font.size
  18. font.Font.underline
  19. font.SysFont
  20. font.get_default_font
  21. font.get_fonts
  22. font.get_init
  23. font.init
  24. font.match_font
  25. font.quit

freetype

  1. module-freetype
  2. freetype.Font
  3. freetype.Font.antialiased
  4. freetype.Font.ascender
  5. freetype.Font.bgcolor
  6. freetype.Font.descender
  7. freetype.Font.fgcolor
  8. freetype.Font.fixed_sizes
  9. freetype.Font.fixed_width
  10. freetype.Font.get_metrics
  11. freetype.Font.get_rect
  12. freetype.Font.get_sized_ascender
  13. freetype.Font.get_sized_descender
  14. freetype.Font.get_sized_glyph_height
  15. freetype.Font.get_sized_height
  16. freetype.Font.get_sizes
  17. freetype.Font.height
  18. freetype.Font.kerning
  19. freetype.Font.name
  20. freetype.Font.oblique
  21. freetype.Font.origin
  22. freetype.Font.pad
  23. freetype.Font.path
  24. freetype.Font.render
  25. freetype.Font.render_raw
  26. freetype.Font.render_raw_to
  27. freetype.Font.render_to
  28. freetype.Font.resolution
  29. freetype.Font.rotation
  30. freetype.Font.scalable
  31. freetype.Font.size
  32. freetype.Font.strength
  33. freetype.Font.strong
  34. freetype.Font.style
  35. freetype.Font.ucs4
  36. freetype.Font.underline
  37. freetype.Font.underline_adjustment
  38. freetype.Font.use_bitmap_strikes
  39. freetype.Font.vertical
  40. freetype.Font.wide
  41. freetype.SysFont
  42. freetype.get_cache_size
  43. freetype.get_default_font
  44. freetype.get_default_resolution
  45. freetype.get_error
  46. freetype.get_init
  47. freetype.get_version
  48. freetype.init
  49. freetype.quit
  50. freetype.set_default_resolution
  51. freetype.was_init

gfxdraw

  1. module-gfxdraw
  2. gfxdraw.aacircle
  3. gfxdraw.aaellipse
  4. gfxdraw.aapolygon
  5. gfxdraw.aatrigon
  6. gfxdraw.arc
  7. gfxdraw.bezier
  8. gfxdraw.box
  9. gfxdraw.circle
  10. gfxdraw.ellipse
  11. gfxdraw.filled_circle
  12. gfxdraw.filled_ellipse
  13. gfxdraw.filled_polygon
  14. gfxdraw.filled_trigon
  15. gfxdraw.hline
  16. gfxdraw.line
  17. gfxdraw.pie
  18. gfxdraw.pixel
  19. gfxdraw.polygon
  20. gfxdraw.rectangle
  21. gfxdraw.textured_polygon
  22. gfxdraw.trigon
  23. gfxdraw.vline

image

  1. module-image
  2. image.frombuffer
  3. image.fromstring
  4. image.get_extended
  5. image.get_sdl_image_version
  6. image.load
  7. image.load_basic
  8. image.load_extended
  9. image.save
  10. image.save_extended
  11. image.tostring

joystick

  1. module-joystick
  2. joystick.Joystick
  3. joystick.Joystick.get_axis
  4. joystick.Joystick.get_ball
  5. joystick.Joystick.get_button
  6. joystick.Joystick.get_guid
  7. joystick.Joystick.get_hat
  8. joystick.Joystick.get_id
  9. joystick.Joystick.get_init
  10. joystick.Joystick.get_instance_id
  11. joystick.Joystick.get_name
  12. joystick.Joystick.get_numaxes
  13. joystick.Joystick.get_numballs
  14. joystick.Joystick.get_numbuttons
  15. joystick.Joystick.get_numhats
  16. joystick.Joystick.get_power_level
  17. joystick.Joystick.init
  18. joystick.Joystick.quit
  19. joystick.get_count
  20. joystick.get_init
  21. joystick.init
  22. joystick.quit

key

  1. module-key
  2. key.get_focused
  3. key.get_mods
  4. key.get_pressed
  5. key.get_repeat
  6. key.key_code
  7. key.name
  8. key.set_mods
  9. key.set_repeat
  10. key.set_text_input_rect
  11. key.start_text_input
  12. key.stop_text_input

mask

  1. module-mask
  2. mask.Mask
  3. mask.Mask.angle
  4. mask.Mask.centroid
  5. mask.Mask.clear
  6. mask.Mask.connected_component
  7. mask.Mask.connected_components
  8. mask.Mask.convolve
  9. mask.Mask.copy
  10. mask.Mask.count
  11. mask.Mask.draw
  12. mask.Mask.erase
  13. mask.Mask.fill
  14. mask.Mask.get_at
  15. mask.Mask.get_bounding_rects
  16. mask.Mask.get_rect
  17. mask.Mask.get_size
  18. mask.Mask.invert
  19. mask.Mask.outline
  20. mask.Mask.overlap
  21. mask.Mask.overlap_area
  22. mask.Mask.overlap_mask
  23. mask.Mask.scale
  24. mask.Mask.set_at
  25. mask.Mask.to_surface
  26. mask.from_surface
  27. mask.from_threshold

math

  1. module-math
  2. math.Vector2
  3. math.Vector2.angle_to
  4. math.Vector2.as_polar
  5. math.Vector2.cross
  6. math.Vector2.distance_squared_to
  7. math.Vector2.distance_to
  8. math.Vector2.dot
  9. math.Vector2.elementwise
  10. math.Vector2.from_polar
  11. math.Vector2.is_normalized
  12. math.Vector2.length
  13. math.Vector2.length_squared
  14. math.Vector2.lerp
  15. math.Vector2.magnitude
  16. math.Vector2.magnitude_squared
  17. math.Vector2.normalize
  18. math.Vector2.normalize_ip
  19. math.Vector2.reflect
  20. math.Vector2.reflect_ip
  21. math.Vector2.rotate
  22. math.Vector2.rotate_ip
  23. math.Vector2.rotate_ip_rad
  24. math.Vector2.rotate_rad
  25. math.Vector2.scale_to_length
  26. math.Vector2.slerp
  27. math.Vector2.update
  28. math.Vector3
  29. math.Vector3.angle_to
  30. math.Vector3.as_spherical
  31. math.Vector3.cross
  32. math.Vector3.distance_squared_to
  33. math.Vector3.distance_to
  34. math.Vector3.dot
  35. math.Vector3.elementwise
  36. math.Vector3.from_spherical
  37. math.Vector3.is_normalized
  38. math.Vector3.length
  39. math.Vector3.length_squared
  40. math.Vector3.lerp
  41. math.Vector3.magnitude
  42. math.Vector3.magnitude_squared
  43. math.Vector3.normalize
  44. math.Vector3.normalize_ip
  45. math.Vector3.reflect
  46. math.Vector3.reflect_ip
  47. math.Vector3.rotate
  48. math.Vector3.rotate_ip
  49. math.Vector3.rotate_ip_rad
  50. math.Vector3.rotate_rad
  51. math.Vector3.rotate_x
  52. math.Vector3.rotate_x_ip
  53. math.Vector3.rotate_x_ip_rad
  54. math.Vector3.rotate_x_rad
  55. math.Vector3.rotate_y
  56. math.Vector3.rotate_y_ip
  57. math.Vector3.rotate_y_ip_rad
  58. math.Vector3.rotate_y_rad
  59. math.Vector3.rotate_z
  60. math.Vector3.rotate_z_ip
  61. math.Vector3.rotate_z_ip_rad
  62. math.Vector3.rotate_z_rad
  63. math.Vector3.scale_to_length
  64. math.Vector3.slerp
  65. math.Vector3.update
  66. math.disable_swizzling
  67. math.enable_swizzling

midi

  1. module-midi
  2. midi.Input
  3. midi.Input.close
  4. midi.Input.poll
  5. midi.Input.read
  6. midi.MidiException
  7. midi.Output
  8. midi.Output.abort
  9. midi.Output.close
  10. midi.Output.note_off
  11. midi.Output.note_on
  12. midi.Output.pitch_bend
  13. midi.Output.set_instrument
  14. midi.Output.write
  15. midi.Output.write_short
  16. midi.Output.write_sys_ex
  17. midi.frequency_to_midi
  18. midi.get_count
  19. midi.get_default_input_id
  20. midi.get_default_output_id
  21. midi.get_device_info
  22. midi.get_init
  23. midi.init
  24. midi.midi_to_ansi_note
  25. midi.midi_to_frequency
  26. midi.midis2events
  27. midi.quit
  28. midi.time

mixer

  1. module-mixer
  2. mixer.Channel
  3. mixer.Channel.fadeout
  4. mixer.Channel.get_busy
  5. mixer.Channel.get_endevent
  6. mixer.Channel.get_queue
  7. mixer.Channel.get_sound
  8. mixer.Channel.get_volume
  9. mixer.Channel.pause
  10. mixer.Channel.play
  11. mixer.Channel.queue
  12. mixer.Channel.set_endevent
  13. mixer.Channel.set_volume
  14. mixer.Channel.stop
  15. mixer.Channel.unpause
  16. mixer.Sound
  17. mixer.Sound.fadeout
  18. mixer.Sound.get_length
  19. mixer.Sound.get_num_channels
  20. mixer.Sound.get_raw
  21. mixer.Sound.get_volume
  22. mixer.Sound.play
  23. mixer.Sound.set_volume
  24. mixer.Sound.stop
  25. mixer.fadeout
  26. mixer.find_channel
  27. mixer.get_busy
  28. mixer.get_init
  29. mixer.get_num_channels
  30. mixer.get_sdl_mixer_version
  31. mixer.init
  32. mixer.pause
  33. mixer.pre_init
  34. mixer.quit
  35. mixer.set_num_channels
  36. mixer.set_reserved
  37. mixer.stop
  38. mixer.unpause

music

  1. module-mixer.music
  2. mixer.music.fadeout
  3. mixer.music.get_busy
  4. mixer.music.get_endevent
  5. mixer.music.get_pos
  6. mixer.music.get_volume
  7. mixer.music.load
  8. mixer.music.pause
  9. mixer.music.play
  10. mixer.music.queue
  11. mixer.music.rewind
  12. mixer.music.set_endevent
  13. mixer.music.set_pos
  14. mixer.music.set_volume
  15. mixer.music.stop
  16. mixer.music.unload
  17. mixer.music.unpause

mouse

  1. mouse
  2. mouse.get_cursor
  3. mouse.get_focused
  4. mouse.get_pos
  5. mouse.get_pressed
  6. mouse.get_rel
  7. mouse.get_visible
  8. mouse.set_cursor
  9. mouse.set_pos
  10. mouse.set_system_cursor
  11. mouse.set_visible

PixelArray

  1. PixelArray
  2. PixelArray.close
  3. PixelArray.compare
  4. PixelArray.extract
  5. PixelArray.itemsize
  6. PixelArray.make_surface
  7. PixelArray.ndim
  8. PixelArray.replace
  9. PixelArray.shape
  10. PixelArray.strides
  11. PixelArray.surface
  12. PixelArray.transpose

pixelcopy

  1. pixelcopy
  2. pixelcopy.array_to_surface
  3. pixelcopy.make_surface
  4. pixelcopy.map_array
  5. pixelcopy.surface_to_array

pygame

  1. pygame
  2. encode_file_path
  3. encode_string
  4. error
  5. get_error
  6. get_init
  7. get_sdl_byteorder
  8. get_sdl_version
  9. init
  10. quit
  11. register_quit
  12. set_error
  13. version.SDL
  14. version.rev
  15. version.ver
  16. version.vernum

Rect

  1. Rect
  2. Rect.clamp
  3. Rect.clamp_ip
  4. Rect.clip
  5. Rect.clipline
  6. Rect.collidedict
  7. Rect.collidedictall
  8. Rect.collidelist
  9. Rect.collidelistall
  10. Rect.collidepoint
  11. Rect.colliderect
  12. Rect.contains
  13. Rect.copy
  14. Rect.fit
  15. Rect.inflate
  16. Rect.inflate_ip
  17. Rect.move
  18. Rect.move_ip
  19. Rect.normalize
  20. Rect.union
  21. Rect.union_ip
  22. Rect.unionall
  23. Rect.unionall_ip
  24. Rect.update

scrap

  1. scrap
  2. scrap.contains
  3. scrap.get
  4. scrap.get_init
  5. scrap.get_types
  6. scrap.init
  7. scrap.lost
  8. scrap.put
  9. scrap.set_mode

sndarray

  1. sndarray
  2. sndarray.array
  3. sndarray.get_arraytype
  4. sndarray.get_arraytypes
  5. sndarray.make_sound
  6. sndarray.samples
  7. sndarray.use_arraytype

sprite

  1. sprite
  2. sprite.DirtySprite
  3. sprite.Group
  4. sprite.Group.add
  5. sprite.Group.clear
  6. sprite.Group.copy
  7. sprite.Group.draw
  8. sprite.Group.empty
  9. sprite.Group.has
  10. sprite.Group.remove
  11. sprite.Group.sprites
  12. sprite.Group.update
  13. sprite.GroupSingle
  14. sprite.LayeredDirty
  15. sprite.LayeredDirty.change_layer
  16. sprite.LayeredDirty.clear
  17. sprite.LayeredDirty.draw
  18. sprite.LayeredDirty.get_clip
  19. sprite.LayeredDirty.repaint_rect
  20. sprite.LayeredDirty.set_clip
  21. sprite.LayeredDirty.set_timing_treshold
  22. sprite.LayeredUpdates
  23. sprite.LayeredUpdates.add
  24. sprite.LayeredUpdates.change_layer
  25. sprite.LayeredUpdates.draw
  26. sprite.LayeredUpdates.get_bottom_layer
  27. sprite.LayeredUpdates.get_layer_of_sprite
  28. sprite.LayeredUpdates.get_sprite
  29. sprite.LayeredUpdates.get_sprites_at
  30. sprite.LayeredUpdates.get_sprites_from_layer
  31. sprite.LayeredUpdates.get_top_layer
  32. sprite.LayeredUpdates.get_top_sprite
  33. sprite.LayeredUpdates.layers
  34. sprite.LayeredUpdates.move_to_back
  35. sprite.LayeredUpdates.move_to_front
  36. sprite.LayeredUpdates.remove_sprites_of_layer
  37. sprite.LayeredUpdates.sprites
  38. sprite.LayeredUpdates.switch_layer
  39. sprite.OrderedUpdates
  40. sprite.RenderClear
  41. sprite.RenderPlain
  42. sprite.RenderUpdates
  43. sprite.RenderUpdates.draw
  44. sprite.Sprite
  45. sprite.Sprite.add
  46. sprite.Sprite.alive
  47. sprite.Sprite.groups
  48. sprite.Sprite.kill
  49. sprite.Sprite.remove
  50. sprite.Sprite.update
  51. sprite.collide_circle
  52. sprite.collide_circle_ratio
  53. sprite.collide_mask
  54. sprite.collide_rect
  55. sprite.collide_rect_ratio
  56. sprite.groupcollide
  57. sprite.spritecollide
  58. sprite.spritecollideany

Surface

  1. Surface
  2. Surface._pixels_address
  3. Surface.blit
  4. Surface.blits
  5. Surface.convert
  6. Surface.convert_alpha
  7. Surface.copy
  8. Surface.fill
  9. Surface.get_abs_offset
  10. Surface.get_abs_parent
  11. Surface.get_alpha
  12. Surface.get_at
  13. Surface.get_at_mapped
  14. Surface.get_bitsize
  15. Surface.get_bounding_rect
  16. Surface.get_buffer
  17. Surface.get_bytesize
  18. Surface.get_clip
  19. Surface.get_colorkey
  20. Surface.get_flags
  21. Surface.get_height
  22. Surface.get_locked
  23. Surface.get_locks
  24. Surface.get_losses
  25. Surface.get_masks
  26. Surface.get_offset
  27. Surface.get_palette
  28. Surface.get_palette_at
  29. Surface.get_parent
  30. Surface.get_pitch
  31. Surface.get_rect
  32. Surface.get_shifts
  33. Surface.get_size
  34. Surface.get_view
  35. Surface.get_width
  36. Surface.lock
  37. Surface.map_rgb
  38. Surface.mustlock
  39. Surface.scroll
  40. Surface.set_alpha
  41. Surface.set_at
  42. Surface.set_clip
  43. Surface.set_colorkey
  44. Surface.set_masks
  45. Surface.set_palette
  46. Surface.set_palette_at
  47. Surface.set_shifts
  48. Surface.subsurface
  49. Surface.unlock
  50. Surface.unmap_rgb

surfarray

  1. surfarray
  2. surfarray.array2d
  3. surfarray.array3d
  4. surfarray.array_alpha
  5. surfarray.array_colorkey
  6. surfarray.blit_array
  7. surfarray.get_arraytype
  8. surfarray.get_arraytypes
  9. surfarray.make_surface
  10. surfarray.map_array
  11. surfarray.pixels2d
  12. surfarray.pixels3d
  13. surfarray.pixels_alpha
  14. surfarray.pixels_blue
  15. surfarray.pixels_green
  16. surfarray.pixels_red
  17. surfarray.use_arraytype

time

  1. time
  2. time.Clock
  3. time.Clock.get_fps
  4. time.Clock.get_rawtime
  5. time.Clock.get_time
  6. time.Clock.tick
  7. time.Clock.tick_busy_loop
  8. time.delay
  9. time.get_ticks
  10. time.set_timer
  11. time.wait

transform

  1. transform
  2. transform.average_color
  3. transform.average_surfaces
  4. transform.chop
  5. transform.flip
  6. transform.get_smoothscale_backend
  7. transform.laplacian
  8. transform.rotate
  9. transform.rotozoom
  10. transform.scale
  11. transform.scale2x
  12. transform.set_smoothscale_backend
  13. transform.smoothscale
  14. transform.threshold


Blog

Этот туториал поможет вам сделать заготовку для простой игры, в которой вы будете перемещать своего персонажа, чтобы избежать столкновения с препятствиями. Вы будете использовать Pygame — набор модулей Python, предназначенных для написания видеоигр. Pygame добавляет функциональность поверх превосходной библиотеки SDL. В последней версии используется Pygame SDL2.

Как Писать Игры На Python С Pygame

Установка библиотеки

Pygame состоит из нескольких модулей с функциями для рисования графики, воспроизведения звуков, обработки ввода с помощью мыши и других вещей, которые вам понадобятся при разработке своей первой игры на Python 3

Для начала работы с библиотекой необходимо добавить ее в локальную среду разработки. На Python Pygame-установка выполняется через pip:

 python -m pip install -U pygame --user

Чтобы убедиться в том, что библиотека работает, запустите встроенный пример игры:

python -m pygame.examples.aliens

Должна запуститься игра, в которой нужно уничтожать летающие тарелки инопланетян.

Есть и другие способы установки для разных операционных систем, компиляция библиотеки из исходников. Смотрите их в документации Pygame.

Игровой цикл

Игровой цикл — это место, где все игровые события происходят, обновляются и отображаются на экране. Как только первоначальная настройка и инициализация переменных завершены, начинается игровой цикл, в котором программа продолжает повторяться снова и снова, пока не произойдет событие типа QUIT.

Ниже приведен тип цикла Game, который мы будем использовать в нашей программе Pygame.

while True:
      # Code
      pygame.display.update()

Изменения в игре не вступают в силу до тех пор, пока не будет выполнена команда display.update(). Поскольку в играх всё безостановочно меняется, функция обновления находится в игровом цикле и тоже выполняется постоянно.

Выход из игрового цикла

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

while True:
    pygame.display.update()
    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
            sys.exit()

Мы вызываем pygame.quit() и sys.exit(), чтобы закрыть окно Pygame и завершить скрипт Python соответственно. Простое использование sys.exit() может привести к зависанию IDE.

Игровые события

Событие происходит, когда пользователь выполняет определенное действие. Например, щелкает мышью или нажимает кнопку на клавиатуре. Pygame записывает каждое происходящее событие.

Вы можете узнать, какие события произошли, вызвав функцию pygame.event.get(). Она возвращает список объектов pygame.event.Event. Для краткости будем называть это объектами событий.

Одним из многих атрибутов (или свойств), которыми обладают объекты событий, является тип — type. Атрибут type сообщает, какое событие представляет объект.

В примере выше использован event.type == QUIT. Он помогает определить, должна игра быть закрыта или нет. Пока пользователь не закроет игру (говоря языком Pygame, не вызовет событие ‘QUIT’), она будет работать в бесконечном цикле.

Игровой экран

Для игры нужно создать окно фиксированного размера, внутри которого будут происходить все события. Ширина и высота этого окна в пикселях передаются в функцию pygame set mode в виде кортежа.

DISPLAYSURF = pygame.display.set_mode((300,300))

Пиксель — наименьшая возможная область на экране. Не существует половины пикселя или четверти пикселя. Поэтому ширина и высота должны быть целыми числами.

Кадровая частота

Если не задать ограничение на частоту кадров, компьютер будет выполнять игровой цикл столько раз, сколько может в течение секунды. Чтобы ограничить его, используйте метод ‘tick(fps)’, где fps — целое число. Метод ‘tick(fps)’ принадлежит классу ‘pygame.time.Clock’ и должен использоваться с объектом этого класса.

FPS = pygame.time.Clock()
FPS.tick(60)

Это может варьироваться от игры к игре, в зависимости от того, как она была разработана, но вы должны стремиться к значению от 30 до 60. Имейте в виду, что, если вы создаете довольно сложную и тяжелую игру, компьютер может не справиться с ней на более высоких кадрах.

Цвета

Pygame использует систему цветов RGB (Red, Green, Blue). Значения для каждого цвета находятся в диапазоне от 0 до 255, всего 256 значений. Сочетание этих трех цветов используется для создания всех цветов, которые вы видите на компьютерах или на любом устройстве с экраном.

Чтобы использовать цвета в Pygame, создают объекты Color, используя значения RGB. Значения RGB должны быть в формате кортежа с тремя значениями для каждого основного цвета.

BLACK = pygame.Color(0, 0, 0)
WHITE = pygame.Color(255, 255, 255)
GREY = pygame.Color(128, 128, 128)
RED = pygame.Color(255, 0, 0)

В работе с цветами есть одна особенность. Например, если вы нарисуете квадрат и зададите ему зеленый цвет, то по умолчанию зелеными станут только границы. Для полной заливки объектов используйте метод ‘fill’. Это сделает квадрат полностью зеленым.

Создание игры

Теперь пришло время заняться самым интересным — разработать первую игру.

Вот так выглядит полный код проекта, который получится у вас после прохождения этого туториала.

# Импортируем библиотеки
import pygame, sys
from pygame.locals import *
import random

# Инициализируем Pygame
pygame.init()

# Ограничиваем количество кадров в секунду
FPS = 60
FramePerSec = pygame.time.Clock()

# Задаем цвет
WHITE = (255, 255, 255)

# Задаем размеры игрового экрана
SCREEN_WIDTH = 400
SCREEN_HEIGHT = 600 

# Отрисовываем экран и заливаем его белым цветом
DISPLAYSURF = pygame.display.set_mode((SCREEN_WIDTH,SCREEN_HEIGHT)))
DISPLAYSURF.fill(WHITE)
pygame.display.set_caption("Game")

# Определяем класс игрока
class Player(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__() 
        self.image = pygame.image.load("Player.png")
        self.rect = self.image.get_rect()
        self.rect.center = (160, 520) 

    def update(self):
        pressed_keys = pygame.key.get_pressed()            
        if self.rect.left > 0:
              if pressed_keys[K_LEFT]:
                  self.rect.move_ip(-5, 0)
        if self.rect.right < SCREEN_WIDTH:        
              if pressed_keys[K_RIGHT]:
                  self.rect.move_ip(5, 0) 

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

# Определяем класс врага
class Enemy(pygame.sprite.Sprite):
      def __init__(self):
        super().__init__() 
        self.image = pygame.image.load("Enemy.png")
        self.rect = self.image.get_rect()
        self.rect.center=(random.randint(40,SCREEN_WIDTH-40),0) 

      def move(self):
        self.rect.move_ip(0,10)
        if (self.rect.bottom > 600):
            self.rect.top = 0
            self.rect.center = (random.randint(30, 370), 0) 

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

# Создаем персонажей
P1 = Player()
E1 = Enemy()

# Определяем игровой цикл
while True:     
    for event in pygame.event.get():              
        if event.type == QUIT:
            pygame.quit()
            sys.exit()
    P1.update()
    E1.move()     

    DISPLAYSURF.fill(WHITE)
    P1.draw(DISPLAYSURF)
    E1.draw(DISPLAYSURF)         

    pygame.display.update()
    FramePerSec.tick(FPS)

Теперь давайте разбирать, какие Pygame Python-команды здесь используются.

Инициализация игры

Создание игры на Python с Pygame начинается с импорта библиотеки. Откройте файл в любой IDE или редакторе кода и добавьте две строки:

import pygame
from pygame.locals import *

Первой строкой вы импортировали модуль Pygame Python 3. Второй строкой вы импортировали все переменные из pygame.locals. 

Можно обойтись без второго импорта. Но он заметно сокращает количество кода. Например, событие выхода из игры без импорта переменных из pygame.locals придется записывать так: ‘pygame.locals.QUIT’. С импортом же синтаксис гораздо короче — для добавления события достаточно написать ‘QUIT’. 

Чтобы использовать случайные значения, импортируйте библиотеку random. Без нее игра будет предсказуемой:

 import random

В начале файла должна быть ещё одна важная строка:

pygame.init()

Эта строка обязательна при использовании библиотеки Pygame. Ее нужно добавить перед любой другой функцией библиотеки, иначе возникнут проблемы с инициализацией. Поэтому вы добавляете init() в начале файла, чтобы исключить появление ошибок.

Определение персонажей

В проекте используется объектно-ориентированный подход. Это позволяет создавать классы, которые становятся основой для разных персонажей. Например, у вас будет один класс врагов (препятствий в игре), а по мере прохождения раундов они будут видоизменяться и получать дополнительные способности.

Сначала определим класс игрока:

class Player(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__() 
        self.image = pygame.image.load("Player.png")
        self.rect = self.image.get_rect()
        self.rect.center = (160, 520)

Функция image.load() принимает на вход файл изображения. Чтобы определить границы спрайта игрока, достаточно вызвать функцию get_rect(). Она автоматически создаст прямоугольник того же размера, что и изображение. Это будет полезно в дальнейшей разработке, когда вы, например, будете реализовывать логику столкновения объектов. Последняя строка self.rect.center определяет начальную позицию персонажа на игровом поле.

def update(self):
    pressed_keys = pygame.key.get_pressed()  
    if self.rect.left > 0:
          if pressed_keys[K_LEFT]:
              self.rect.move_ip(-5, 0)
    if self.rect.left > 0:       
          if pressed_keys[K_RIGHT]:
              self.rect.move_ip(5, 0)

Метод update управляет движением игрока. При его вызове выполняется проверка, нажаты ли клавиши.  

В этом проекте нас интересует только движение влево и вправо, которое позволяет избегать препятствий. Если игрок нажимает на левую стрелку, выполняется перемещение его персонажа налево. Аналогично реализована логика движения направо.

Метод move_ip() принимает два параметра. Первый параметр — это расстояние в пикселях, на которое необходимо переместить объект по горизонтали. Второй параметр — расстояние, на которое необходимо переместить объект по вертикали.

Операторы if self.rect.left > 0 и if self.rect.left > 0 гарантируют, что игрок не выйдет за пределы игрового поля.

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

Функция blit() принимает параметры. Первый — объект для отрисовки, а второй — его спрайт. Поскольку вы используете изображение, то передаете self.image в качестве объекта для отрисовки. 

Класс врага устроен очень похоже. Единственное отличие — использование генератора случайных чисел:

self.rect.center=(random.randint(40,SCREEN_WIDTH-40),0) 

Это нужно для того, чтобы препятствие каждый раз появлялось в новом месте. Иначе игра будет предсказуемой.

Игровой цикл

И самая важная часть — игровой цикл:

while True:     
    for event in pygame.event.get():              
        if event.type == QUIT:
            pygame.quit()
            sys.exit()
    P1.update()
    E1.move()     

    DISPLAYSURF.fill(WHITE)
    P1.draw(DISPLAYSURF)
    E1.draw(DISPLAYSURF)

    pygame.display.update()
    FramePerSec.tick(FPS)

Цикл выполняется бесконечно, пока пользователь не закончит игру. Это самая простая реализация. На практике к завершению игры могут приводить разные события — например, исчерпание лимита жизней персонажа.

Сначала вызываются функции update для классов Enemy и Player. Далее цикл обновляет экран с помощью DISPLAY.fill(WHITE). Наконец, вызывается функция draw для отрисовки объектов на экране.

Наконец, команда pygame.display.update() обновляет экран, выводя все изменения, которые произошли до этого момента. Функция tick() гарантирует, что количество кадров в секунду при этом не превышает установленного ранее значения FPS.

Заключение

Игра готова. Она пока не настолько хороша, чтобы арендовать сервер для хостинга на cloud.timeweb.com и ждать наплыва игроков. Но это ваша первая игра на Питон и теперь вы знаете, как сделать ее лучше. Например, как добавить персонажу движение вверх и вниз или изменить логику появления препятствий.

Возможностей для совершенствования проекта очень много. Например, можно сделать двумерную игру трехмерной, используя Pygame raycast. Да, на Pygame не получится разработать клона Cyberpunk 2077, но свою версию Wolfenstein 3D сделать реально. 

Есть большое количество туториалов и гайдов по использованию Pygame на русском языке. Они помогут изучить не только особенности библиотеки, но и некоторые универсальные концепции геймдева. Если позже вы переключитесь на более продвинутый игровой движок, многие из этих концепций останутся актуальными.

Создание игр – перспективное направление разработки, которое стремительно развивается в 21 веке. Для того, чтобы программировать развлекательные продукты, нужно для начала выбрать специализированный язык, а затем изучить его особенности и инструменты. Небольшие проекты можно сделать и на Python.

Статья расскажет о том, какие преимущества и недостатки имеет соответствующий язык разработки, а также познакомит с Pygame – одним из мощнейших инструментов при создании the game. Также будут изучены уже написанные проекты.

Определение

Python – высокоуровневый язык программирования общего назначения. Используется для создания самых разных приложений: от игровых до бизнес-программ. Поддерживает концепции объектно-ориентированной разработки.

Python – язык с динамической типизацией данных. Он является достаточно простым для изучения, благодаря чему его активно используют новички. The first game написать на Python будет не слишком трудно даже с минимальными знаниями.

Плюсы

Python является языком разработки со следующими преимуществами:

  • стабильное функционирование;
  • читабельный и простой код;
  • элементарный синтаксис, в основе которого лежит язык ABC;
  • универсальность – одинакового подходит как для the business apps, так и для игр;
  • в небольших приложениях работает достаточно быстро;
  • наличие динамической типизации.

У The Python имеется обширный спектр фреймворков, а также встроенных инструментов и библиотек. Все это помогает with the game programming.

Минусы

Недостатков у Питона не очень много. К ним относят:

  • отсутствие строгой типизации;
  • итоговый объем получившегося приложения.

Из-за «веса» получаемые games can be slowly. Приложения рискую медленно работать, а также сильно нагружать операционную систему устройства. Именно поэтому for the game programming Питон используется тогда, когда речь идет о не самых крупных проектах.

Игровой цикл

Игровой цикл – это объект, который заставляет программный код загружаться из раза в раз. В игре им выступает кадр. В нем может происходить множество действий. Они разделяются на несколько категорий:

  1. Ввод данных. Производится со стороны непосредственного пользователя.
  2. Обновление кадра.
  3. Визуализация. Эта операция отвечает за вывод изображения на экран. В процессе производится отрисовка элементов там, где они должны были располагаться по первоначальной задумке. 

In the big projects появляется искусственный интеллект и физика. Для создания полноценной игры нужно разобраться с воспроизведением звуков и музыки. Иногда в ней предусматривается набор очков, повышение уровня, а также индикаторы жизни.

The Pygame – мощный инструмент разработчика развлекательного программного обеспечения. Фреймворк (библиотека), совместимая с Python 3.0. Данный модуль вышел в 2000 году и стремительно развивался. Его поддержка производится по сей день.

Игры, созданные при помощи the Pygame – это масштабируемые проекты. Они одинаково хорошо запускаются on the mobile и ПК.

Модуль Pygame:

  • является кроссплатформенным;
  • обладает открытым исходным кодом;
  • достаточно прост в изучении;
  • имеет неплохую поддержку;
  • обладает зрелой library.

Найти tutorial of the Pygame не составит особого труда – в сети полно документации (documents) и видео-гайдов. Данный модуль является обязательным для изучения всеми, кто планирует писать игры на Питоне. Это его ключевое предназначение.

Pygame Platform – это платформа, которая используется при разработке мультимедийных приложений с графическим интерфейсом.

Начало работы

Для того, чтобы использовать данный модуль, его нужно сначала инициализировать. Скачивается библиотека с сервиса pygame org. Здесь же можно найти documentation and tutorials по рассматриваемой «платформе».

Перед созданием проекта потребуется:

  1. Изучить основы программирования to the Python language.
  2. Использовать команду pip install pygame. Она отвечает за инициализацию.

Теперь можно формировать проект и редактировать его.

Пример приложения

Pygame Platform – инструмент, помогающий создавать не только простые приложения, но и достаточно крупные игры. Вот элементарный пример кода:

import pygame

import sys

pygame.init()

screen = pygame.display.set_mode((1200, 800))

while True:

    for event in pygame.event.get():

        if event.type == pygame.QUIT:

            pygame.quit()

            sys.exit()

Здесь:

  • import pygame отвечает за импорт libraries, включенный to the module;
  • init() используется для подготовки модулей к работе;
  • screen отвечает за создание графического окна, передав в set_mode() разрешение в качестве парный цифр;
  • while True – основной цикл, перехватывающий событие закрытия основного графического окна посетителем.

После наступления желаемого события происходит завершение работы с библиотекой при помощи функции quit. Exit() отвечает за прекращение использования всего итогового приложения.

Рисование фигур

While running Pygame Platform, разработчикам может потребуется изображение геометрических фигур. Прямоугольные объекты представлены типом Rect:

Создать объект соответствующего типа in the program легко – нужно указать координаты левого верхнего угла прямоугольника, а также длины его сторон:

Здесь стоит обратить внимание на то, что начало координат расположено in the left corner окна, сверху. В изучаемой библиотеке функции отображения геометрических фигур расположены в модуле под названием draw.

Изначально все графические объекты, которые хочется разместить на основном экране, сначала попадают в специальный буфер of the platform. Отображение изменений производится при помощи функции flip.

Любой tutorial расскажет о функциях рисования графических фигур:

  1. Line. Позволяет рисовать линию на поверхности с заданным цветом и началом. Также предусматривается конец в точке end_pos и возможность указания толщины линии.
  2. Lines. Рисует линию, которая соединяет точки последовательности. Каждая из них представлена в приложении координатной парой. Если третий параметр (closed) – это true, конечная точка будет соединена с начальной.
  3. Circle. Точка pos здесь – это центр. Если толщина линии будет равна нулю, окружность закрасится.
  4. Ellipse. Функция, которую уроки по рассматриваемому модулю описывают как возможность нарисовать эллипс, ограниченный прямоугольником Rect. Если толщина линии равняется нулю, фигура будет закрашена.

Еще один вариант, который поддерживает библиотека Pygame – это рисование полигонов. Обозначается как polygon. Это – последовательность pointlist на заданной поверхности выбранного цвета. Каждая точка – это пара координат. Если width равен нулю, получившийся многоугольник будет закрашен.

Цвета

Цвета в модуле представлены моделью RGB. Посмотреть ее можно на Wikipedia org. Значение данного параметра задается в рамках диапазона от 0 до 255 включительно. Первая характеристика указывает на количество красного, вторая – зеленого, третья – голубого. Чем меньше значение, тем более темным окажется оттенок.

Вот несколько примеров, которые используют различные platforms:

  • белый – (255, 255, 255);
  • красный – (255, 0, 0);
  • черный – (0, 0, 0).

Любой tutorial по Pygame в Python укажет на то, что модуль color включает в себя словарь – THECOLORS.

Его ключи – это названия разных цветовых гамм. Подключается он при помощи команды, представленной выше.

Текст и шрифт

Pygame documentation на сайте Питона org содержит данные о работе с текстом и шрифтами. Последние – это группы символов, которые объединены по стилистическому или иному признаку. Шрифты в библиотеке представлены типом под названием Font.

Для того, чтобы создать объект Font на основе уже имеющегося шрифта в системе, нужно вызвать функцию:

Здесь:

  • параметр name отвечает за передачу функции имени шрифта;
  • size – это размер «символов» в пунктах;
  • bold и italic – особенности начертания.

Списки уже имеющихся шрифтов в системе удается получить при помощи команды get_fonts():

Теперь при помощи метода render для объекта Font нужно получить изображение с текстом. Последний передается методу built() для отрисовки на основном дисплее устройства:

Тест при обработке соответствующего кода будет располагаться по координатам (50, 50).

Класс GameObject

В официальной documentation рассматриваемого модуля выделяется объект GameObject. Он представлен визуальным элементом, который знает, как рендерить самого себя. Позволяет хранить границы и перемещаться. С аналогичными возможностями на изучаемой платформе есть класс Sprite. Новичкам он не нужен.

Этот код работает так:

  1. GameObject согласно tutorial document используется в виде базового класса других объектов в играх.
  2. Отвечает за разнообразие свойств прямоугольника.
  3. Метод update() перемещает объект с установленной (текущей) скоростью.
  4. Метод draw() должен определяется подклассами. Он ничего не предпринимает в программном коде.

Для создания собственной игры через «Пигейм»также потребуется знать the class Game.

Класс Game

Это – игровое ядро. Оно выполняется в основном цикле. Наделен полезными инструментами. Обладает такими методами:

  1. Init. Используется за инициализацию Pygame, шрифтов, а также микшера звуков. Three вызова нужны, чтобы задействовать в исходном коде только нужные элементы, а также держать подсистемы под контролем. С его помощью создаются фоны, основная поверхность и таймер с поддержкой отображения частоты кадров.
  2. Update и draw. Вызывают соответствующие методы. При наложении объектов на дисплее, порядок списка объектов будет определять, что рендерится изначально.
  3. Handle_events(). Метод, за счет которого прослушиваются генерируемые события. Сюда можно отнести нажатие на кнопки мыши, а также события клавиш. Каждое действие вызывает все функции-обработки, которые проходят обработку событий.

Также используется метод run(). Он отвечает за работоспособность основного цикла. Используется до получения в значении game_over итога «ложь».

Готовые проекты – наглядные примеры

При помощи Pygame Python создаются довольно крупные проекты. Сейчас самыми известными среди них являются:

  • EVE Online;
  • Battlefield;
  • Mount and Blade;
  • Civilization 4.

Начать работу с упомянутым модулем можно, посмотрев эти уроки. А можно закончить специализированные дистанционные компьютерные курсы.

Создание игр — это увлекательный процесс, который может быть достаточно сложным для начинающих разработчиков. В этой статье я подробно объясню, как создать игру с нуля на языке программирования Python.

Шаг 1: Установка необходимых инструментов

Первым шагом в создании игры на Python является установка необходимых инструментов. Вам понадобится установить Python, библиотеку Pygame и интегрированную среду разработки (IDE), такую как PyCharm или Visual Studio Code. Убедитесь, что у вас установлена последняя версия Python и Pygame.

Шаг 2: Создание окна игры

Создание окна игры — это первый шаг в создании игры. Для создания окна игры в Pygame нужно импортировать библиотеку и создать экран. Создание экрана можно выполнить следующим образом:

import pygame
pygame.init()
screen = pygame.display.set_mode((800, 600))

В этом примере мы импортируем библиотеку Pygame, инициализируем ее и создаем экран размером 800 на 600 пикселей.

Шаг 3: Добавление спрайтов

Спрайты — это основные объекты в игре, такие как игрок, враги и предметы. Для добавления спрайтов в игру, мы должны создать класс спрайта. В этом классе мы можем задать свойства и методы спрайта, такие как его координаты, скорость и изображение.

class Player(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.Surface((50, 50))
self.image.fill((255, 255, 255))
self.rect = self.image.get_rect()
self.rect.x = 50
self.rect.y = 50

В этом примере мы создаем класс Player и определяем его свойства, такие как изображение, координаты и размеры. Класс Player наследуется от класса Sprite, что позволяет использовать его в группе спрайтов.

Шаг 4: Обработка событий

Для того, чтобы игрок мог управлять спрайтом, нам нужно обработать события в игре. Это может быть событие нажатия клавиши на клавиатуре, клик мыши или другие действия игрока.

running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
player.rect.x -= 5
if keys[pygame.K_RIGHT]:
player.rect.x += 5
if keys[pygame.K_UP]:
player.rect.x += 5
if keys[pygame.K_DOWN]:
player.rect.y += 5
screen.fill((0, 0, 0))
all_sprites.draw(screen)
pygame.display.flip()
pygame.quit()

В этом примере мы создаем цикл while, который обрабатывает события в игре. Мы проверяем каждое событие, чтобы убедиться, что оно не является событием завершения игры (QUIT). Затем мы проверяем, какие клавиши были нажаты, и обновляем координаты спрайта в соответствии с этими нажатиями. Мы также очищаем экран, рисуем спрайты и обновляем экран с помощью метода flip().

Шаг 5: Добавление коллизий

Коллизии — это взаимодействие между спрайтами в игре. Например, когда игрок сталкивается с врагом, это должно вызвать событие. Для добавления коллизий в игру нам нужно определить, какие спрайты должны взаимодействовать между собой.

class Enemy(pygame.sprite.Sprite):
def init(self):
super().init()
self.image = pygame.Surface((50, 50))
self.image.fill((255, 0, 0))
self.rect = self.image.get_rect()
self.rect.x = 500
self.rect.y = 500

player = Player()
enemy = Enemy()

all_sprites = pygame.sprite.Group()
all_sprites.add(player)
all_sprites.add(enemy)

while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
player.rect.x -= 5
if keys[pygame.K_RIGHT]:
player.rect.x += 5
if keys[pygame.K_UP]:
player.rect.y -= 5
if keys[pygame.K_DOWN]:
player.rect.y += 5

if pygame.sprite.collide_rect(player, enemy):
print(«Collision!»)

screen.fill((0, 0, 0))
all_sprites.draw(screen)
pygame.display.flip()
pygame.quit()

В этом примере мы создаем класс Enemy и добавляем его в группу спрайтов. Затем мы проверяем коллизии между игроком и врагом с помощью метода collide_rect(). Если происходит столкновение, мы выводим сообщение в консоль.

Шаг 6: Добавление звука и музыки

Для того, чтобы игра звучала более реалистично, мы можем добавить звуковые эффекты и музыку. Для этого мы должны загрузить аудиофайлы и использовать методы play() или stop() для воспроизведения или остановки звуков.

pygame.mixer.init()
pygame.mixer.music.load(«music.mp3»)
pygame.mixer.music.play()

sound_effect = pygame.mixer.Sound(«sound_effect.wav»)
sound_effect.play

В этом примере мы инициализируем модуль pygame.mixer для работы с звуком и загружаем музыкальный файл и звуковой эффект. Мы используем метод play() для воспроизведения музыки и звукового эффекта.

Шаг 7: Добавление меню и интерфейса

Чтобы игрок мог начать игру и управлять ею, нам нужно создать меню и интерфейс пользователя (UI). Для этого мы можем использовать модуль pygame_gui, который предоставляет инструменты для создания пользовательского интерфейса.

import pygame_gui

pygame.init()

# Создание окна
screen_width = 800
screen_height = 600
screen = pygame.display.set_mode((screen_width, screen_height))

# Создание менеджера GUI
ui_manager = pygame_gui.UIManager((screen_width, screen_height))

# Создание кнопки «Play»
play_button = pygame_gui.elements.UIButton(
relative_rect=pygame.Rect((350, 275), (100, 50)),
text=’Play’,
manager=ui_manager)

# Основной цикл игры
running = True
clock = pygame.time.Clock()

while running:
time_delta = clock.tick(60) / 1000.0

for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False

# Обработка событий GUI
if event.type == pygame.USEREVENT:
if event.user_type == pygame_gui.UI_BUTTON_PRESSED:
if event.ui_element == play_button:
print(«Play button pressed!»)

# Обработка событий pygame
ui_manager.process_events(event)

ui_manager.update(time_delta)

# Отрисовка GUI
ui_manager.draw_ui(screen)

pygame.display.update()

pygame.quit()

В этом примере мы создаем окно и менеджер GUI, а затем создаем кнопку «Play». Мы также создаем цикл обработки событий, который обрабатывает события GUI и pygame. Мы обновляем менеджер GUI и отрисовываем интерфейс пользователя.

Шаг 8: Добавление сохранения и загрузки

Чтобы игрок мог сохранять свой прогресс в игре и продолжать играть позже, мы можем добавить функции сохранения и загрузки. Для этого мы можем использовать модуль pickle, который позволяет сохранять и загружать объекты Python в файлы.

import pickle

class Game:
def __init__(self):
self.score = 0
self.level = 1

def save(self, filename):
with open(filename, «wb») as f:
pickle.dump(self, f)

@staticmethod
def load(filename):
with open(filename, «rb») as f:
return pickle.load(f)

game = Game()
game.save(«savegame.pickle»)

loaded_game = Game.load(«savegame.pickle»)
print(loaded_game.score)
print(loaded_game.level)

В этом примере мы создаем класс Game, который содержит данные о текущем состоянии игры. Мы также добавляем методы save() и load(), которые сохраняют и загружают объект Game в файл с помощью модуля pickle. Мы создаем объект Game, сохраняем его в файл и затем загружаем его из файла и выводим его свойства score и level.

Чтобы добавить сохранение и загрузку в нашу игру, мы можем сохранять объект Game после каждого уровня или после завершения игры. Мы можем также загружать сохраненную игру при запуске игры.

Шаг 9: Добавление искусственного интеллекта

Чтобы наша игра была более интересной и вызывала больше эмоций, мы можем добавить искусственный интеллект (AI), который будет управлять поведением некоторых объектов в игре. Например, мы можем создать противника, который будет убегать от игрока или атаковать его.

Для создания искусственного интеллекта мы можем использовать алгоритмы машинного обучения или простые правила поведения. В нашем примере мы будем использовать простые правила поведения.

class Enemy:
def __init__(self, x, y):
self.x = x
self.y = y
self.speed = 5

def move_towards_player(self, player_x, player_y):
if self.x < player_x:
self.x += self.speed
elif self.x > player_x:
self.x -= self.speed

if self.y < player_y:
self.y += self.speed
elif self.y > player_y:
self.y -= self.speed

enemy = Enemy(100, 100)

# Основной цикл игры
running = True
clock = pygame.time.Clock()

while running:
time_delta = clock.tick(60) / 1000.0

for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False

# Искусственный интеллект
enemy.move_towards_player(player_x, player_y)

# Отрисовка игровых объектов
screen.fill((255, 255, 255))
pygame.draw.circle(screen, (255, 0, 0), (enemy.x, enemy.y), 10)
pygame.draw.circle(screen, (0, 0, 255), (player_x, player_y), 10)

pygame.display.update()

pygame.quit()

В этом примере мы создаем класс Enemy, который содержит координаты и скорость противника. Мы также добавляем метод move_towards_player(), который управляет движением противника к игроку.

Мы создаем объект Enemy и добавляем искусственный интеллект в наш основной цикл игры. Мы также отрисовываем игровые объекты и обновляем экран.

Шаг 10: Тестирование и отладка

Последний шаг в создании игры — это тестировение и отладка. В процессе тестирования мы должны убедиться, что игра работает правильно и не вызывает ошибок.

Для тестирования мы можем протестировать каждый компонент игры отдельно и затем тестировать игру в целом. Мы можем также использовать отладочные инструменты, такие как print() и pdb, для выявления ошибок и устранения их.

import pdb

# Основной цикл игры
running = True
clock = pygame.time.Clock()

while running:
time_delta = clock.tick(60) / 1000.0

for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False

# Искусственный интеллект
enemy.move_towards_player(player_x, player_y)

# Отрисовка игровых объектов
screen.fill((255, 255, 255))
pygame.draw.circle(screen, (255, 0, 0), (enemy.x, enemy.y), 10)
pygame.draw.circle(screen, (0, 0, 255), (player_x, player_y), 10)

pygame.display.update()

# Отладка
pdb.set_trace()
print(«Player x: «, player_x)
print(«Player y: «, player_y)
print(«Enemy x: «, enemy.x)
print(«Enemy y: «, enemy.y)

pygame.quit()

В этом примере мы добавляем отладку с помощью pdb. Мы также добавляем команды print() для отображения значений переменных в консоли.

Шаг 11: Оптимизация и улучшение производительности

Когда игра полностью готова, мы можем оптимизировать ее производительность для того, чтобы она работала более быстро и без лагов.

Некоторые способы оптимизации:

  • Использование меньшего количества изображений с более низким разрешением.
  • Использование более эффективных алгоритмов для обработки коллизий.
  • Использование многопоточности или асинхронности для улучшения производительности.

Шаг 12: Публикация игры

После того, как игра полностью готова и протестирована, мы можем опубликовать ее на различных платформах, таких как Steam, App Store или Google Play.

Для публикации игры мы должны создать пакет, который содержит все необходимые файлы и зависимости, и затем загрузить его на соответствующую платформу. Мы также должны написать описание игры, создать скриншоты и видео, и определить цену.

Заключение

В этой статье мы рассмотрели шаги по созданию игры с нуля на языке Python. Мы начали с изучения основных понятий и концепций игровой разработки, затем создали простую игру с использованием библиотеки Pygame.

Мы прошли через все основные шаги, начиная с создания игровых объектов и обработки пользовательского ввода, и заканчивая добавлением звуков, музыки и анимации. Мы также рассмотрели важные концепции, такие как управление состоянием и отладка.

Когда игра была готова, мы рассмотрели вопросы производительности и оптимизации, а также публикации игры на различных платформах.

Хотя создание игр может быть сложным процессом, использование языка Python и библиотеки Pygame делает его более доступным. С помощью этой статьи вы сможете создать свою собственную игру с нуля на Python.

Понравилась статья? Поделить с друзьями:
  • Металлоискатель tianxun tx 850 инструкция на русском языке
  • Баксепт форте инструкция по применению цена
  • Должностная инструкция зам директора по увр по профстандартам
  • Пунарнава инструкция по применению в таблетках отзывы
  • Серебряный путь железная дорога инструкция по сборке