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

Pygame - это библиотека для разработки игр и мультимедийных приложений на языке Python. Она была создана в 2000 году программистом из Ирландии, Питером Линдером, как ответ на отсутствие подобных инструментов для Python на тот момент.
Первоначально Pygame была создана для работы с графикой и звуком, но со временем она стала поддерживать все больше функций, таких как работа с мышью, клавиатурой, сетью и т.д.
За годы своего существования Pygame стала популярной среди разработчиков игр и мультимедийных приложений, благодаря своей простоте и удобству использования. Сегодня Pygame является одной из самых популярных библиотек для разработки игр на Python.
Цель
Мы будем создавать простенькую аркадную по типу Space Invaders для двух игроков. Игроки управляют космическим кораблем и выпускают друг по другу снаряды. У каждого игрока есть некоторое количество жизней. Первый игрок потративший все жизни считается проигравшим.

Ссылка на репозиторий с готовой игрой, если вам вздумается сразу скачать готовый код и посмотреть результат.
Настройка окружения
Итак, приступим.
Создадим новый проект и файл main.py

Теперь нам необходимо установить библиотеку pygame в наш проект. Воспользуемся пакетным менеджером pip (он устанавливается вместе с Python)
Откройте терминал для ввода команды установки. Если вы используете VS Code вы можете открыть терминал в текущей папке при помощи кнопок на панели инструментов.

Вводим команду: pip install pygame

Отлично. Можем начинать создание игры.
Создания окна игры
Перепишите следующий код в файл main.py
Я буду помечать код комментариями, чтобы вам было понятно что происходит на каждой строчке.
1# Подключаем игровой движок Pygame
2import pygame
3
4# Подготавливаем необходимые модули Pygame
5pygame.init()
6
7### Константы ###
8# Константы размера окна
9WIDTH = 600
10HEIGHT = 300
11
12# Задаем размеры игрового окна
13screen = pygame.display.set_mode((WIDTH, HEIGHT))
14
15# Запускаем бесконечный цикл программы
16# Это делается чтобы программа не завершалась и постоянно рисовала новые кадры игры
17while True:
18 pygame.display.update()
Запустите программу. Вы должны увидеть окно черного цвета с разрешением 600 на 300 пикселей.
Обратите внимание, что кнопки свернуть, и закрыть программу неактивны.

Давайте добавим возможность свернуть и закрыть игру при помощи стандартных кнопок.
Для этого в бесконечный цикл добавьте следующий код:
1# Запускаем бесконечный цикл программы
2# Это делается чтобы программа не завершалась и постоянно рисовала новые кадры игры
3while True:
4 # Постоянно проверяем события игры и если присутствует событие Выход - останавливаем игру.
5 for event in pygame.event.get():
6 if event.type == pygame.QUIT:
7 pygame.quit()
8
9 # Обновляем кадры игры
10 pygame.display.update()
В бесконечном цикле мы проверяем, не случилось ли события QUIT (выход), в процессе работы программы и если пользователь нажал на выход, значит мы зарегистрировали событие QUIT - закрываем игру при помощи команды pygame.quit()
Рисуем задний фон
Теперь давайте нарисуем задник нашей игры. Сохраните картинку и положите ее в директорию assets (предварительно создав ее) в корне директории вашей игры.


Так же нам понадобится модуль os. Модуль os позволяет работать с файловой системой компьютера, а именно, поможет нам загрузить картинку.
Загрузим картинку в память при помощи следующего кода:
1# Подключаем модуль для работы с файловой системой
2import os
3
4# Загружаем изображение в память
5SPACE_IMAGE = pygame.image.load(os.path.join('./assets', 'space.jpg'))
6
7# Создаем объект фона с разрешением окна
8SPACE_BG = pygame.transform.scale(SPACE_IMAGE, (WIDTH, HEIGHT))
И теперь достаточно поместить вызов screen.blit(SPACE, (0, 0)) внутрь нашего бесконечного цикла рисующего карды и фон будет виден игроку. Метод blit позволяет наложить одно изображение на другое. В нашем случае нам нужно наложит изображение поверх окна screen.
1# Запускаем бесконечный цикл программы
2# Это делается чтобы программа не завершалась и постоянно рисовала новые кадры игры
3while True:
4 # Рисуем изображение на заднем фоне
5 screen.blit(SPACE_BG, (0, 0))
Промежуточный результат #1
Работает:
- Кнопка закрыть/свернуть
- Отображается задний фон
1# Подключаем игровой движок Pygame
2import pygame
3# Подключаем модуль для работы с файловой системой
4import os
5
6# Подготавливаем необходимые модули Pygame
7pygame.init()
8
9### Константы ###
10# Константы размера окна
11WIDTH = 600
12HEIGHT = 300
13
14# Задаем размеры игрового окна
15screen = pygame.display.set_mode((WIDTH, HEIGHT))
16
17# Загружаем изображение в память
18SPACE_IMAGE = pygame.image.load(os.path.join('./assets', 'space.jpg'))
19
20# Создаем объект фона с разрешением окна
21SPACE_BG = pygame.transform.scale(SPACE_IMAGE, (WIDTH, HEIGHT))
22
23# Запускаем бесконечный цикл программы
24# Это делается чтобы программа не завершалась и постоянно рисовала новые кадры игры
25while True:
26 # Рисуем изображение на заднем фоне
27 screen.blit(SPACE_BG, (0, 0))
28
29 # Постоянно проверяем события игры и если присутствует событие Выход - останавливаем игру.
30 for event in pygame.event.get():
31 if event.type == pygame.QUIT:
32 pygame.quit()
33
34 # Обновляем кадры игры
35 pygame.display.update()
Разделитель игрового экрана
Добавим на экран визуальный разделитель экрана - границу которую игроки не могут пересечь, оставаясь на своей стороне поля.
Создадим объект прямоугольник.
1# Формируем объект границы
2BORDER = pygame.Rect(WIDTH//2 - 5, 0, 10, HEIGHT)
3
Обратите внимание, первые два аргумента функции это x и y расположения прямоугольника, а третий и четвертый аргументы это ширина и высота прямоугольника. Ширина прямоугольника 10, а высота такая же как высота экрана игры. По y прямоугольник начинается от верхнего края экрана, а вот по x мы берем ширину экрана, делим ее на 2 и отнимаем 5 (половину ширины прямоугольника). Благодаря этому прямоугольник располагается прямо посередине экрана игры. Осталось только отрисовать этот объект. Добавим отрисовку в бесконечный цикл, рядом с отрисовкой фона.
1# Рисуем прямоугольник
2pygame.draw.rect(screen, "white", BORDER)
Метод rect объекта draw позволяет отрисовать прямоугольник. Первый аргумент screeen указывает где нужно отрисовать, второй аргумент задает цвет, третий аргумент задает сам объект рисования, наш BORDER.
Должно получиться вот так:

Промежуточный результат #2
Работает:
- Кнопка закрыть/свернуть
- Отображается задний фон
- Разделитель экрана
1# Подключаем игровой движок Pygame
2import pygame
3# Подключаем модуль для работы с файловой системой
4import os
5
6# Подготавливаем необходимые модули Pygame
7pygame.init()
8
9### Константы ###
10# Константы размера окна
11WIDTH = 600
12HEIGHT = 300
13
14# Задаем размеры игрового окна
15screen = pygame.display.set_mode((WIDTH, HEIGHT))
16
17# Загружаем изображение в память
18SPACE_IMAGE = pygame.image.load(os.path.join('./assets', 'space.jpg'))
19
20# Создаем объект фона с разрешением окна
21SPACE_BG = pygame.transform.scale(SPACE_IMAGE, (WIDTH, HEIGHT))
22
23# Формируем объект границы
24BORDER = pygame.Rect(WIDTH//2 - 2, 0, 4, HEIGHT)
25
26# Запускаем бесконечный цикл программы
27# Это делается чтобы программа не завершалась и постоянно рисовала новые кадры игры
28while True:
29 # Рисуем изображение на заднем фоне
30 screen.blit(SPACE_BG, (0, 0))
31
32 # Рисуем прямоугольник
33 pygame.draw.rect(screen, "white", BORDER)
34
35 # Постоянно проверяем события игры и если присутствует событие Выход - останавливаем игру.
36 for event in pygame.event.get():
37 if event.type == pygame.QUIT:
38 pygame.quit()
39
40 # Обновляем кадры игры
41 pygame.display.update()
Создаем игрока
Давайте нарисуем игроков и зададим им движение.
Ниже представлены две картинки: Красный космический корабль и Желтый космический корабль.
Скопируйте эти изображения в директорию assets вашего проекта под именами: spaceship_red.png и spaceship_yellow.png


Создадим две переменных, ширину и высоту кораблей. Добавьте их к блоку константы.
1# Размеры корабля
2SPACESHIP_WIDTH = 55
3SPACESHIP_HEIGHT = 40
В следующем участке кода, мы загружаем изображения красного и желтого кораблей и при помощи rotate разворачиваем изображения в нужную сторону.
1# Загружаем изображение красного корабля
2RED_SPACESHIP_IMAGE = pygame.image.load(
3 os.path.join('./assets', 'spaceship_red.png'))
4# Разворачиваем изображение в нужном направлении
5RED_SPACESHIP = pygame.transform.rotate(pygame.transform.scale(
6 RED_SPACESHIP_IMAGE, (SPACESHIP_WIDTH, SPACESHIP_HEIGHT)), 90)
7
8# Загружаем изображение желтого корабля
9YELLOW_SPACESHIP_IMAGE = pygame.image.load(
10 os.path.join('./assets', 'spaceship_yellow.png'))
11# Разворачиваем изображение в нужном направлении
12YELLOW_SPACESHIP = pygame.transform.rotate(pygame.transform.scale(
13 YELLOW_SPACESHIP_IMAGE, (SPACESHIP_WIDTH, SPACESHIP_HEIGHT)), 270)
Картинки загрузили, теперь нужно создать два объекта прямоугольника для будущих кораблей. Так как объекты Rect хранят ширину, высоту, и координаты x и y - это идеальные кандидаты для хранения данных кораблей.
1# Создаем два объекта/прямоугольника
2red = pygame.Rect(100, 150, SPACESHIP_WIDTH, SPACESHIP_HEIGHT)
3yellow = pygame.Rect(500, 150, SPACESHIP_WIDTH, SPACESHIP_HEIGHT)
Отлично, осталось только отрисовать наши корабли на экране. Добавьте следующий код в бесконечный цикл отрисовки экрана.
1# Рисуем корабли
2screen.blit(YELLOW_SPACESHIP, (yellow.x, yellow.y))
3screen.blit(RED_SPACESHIP, (red.x, red.y))
Промежуточный результат #3
Работает:
- Кнопка закрыть/свернуть
- Отображается задний фон
- Разделитель экрана
- Отрисовка игроков
1# Подключаем игровой движок Pygame
2import pygame
3# Подключаем модуль для работы с файловой системой
4import os
5
6# Подготавливаем необходимые модули Pygame
7pygame.init()
8
9### Константы ###
10# Константы размера окна
11WIDTH = 600
12HEIGHT = 300
13# Размеры корабля
14SPACESHIP_WIDTH = 55
15SPACESHIP_HEIGHT = 40
16
17# Задаем размеры игрового окна
18screen = pygame.display.set_mode((WIDTH, HEIGHT))
19
20# Загружаем изображение в память
21SPACE_IMAGE = pygame.image.load(os.path.join('./assets', 'space.jpg'))
22
23# Создаем объект фона с разрешением окна
24SPACE_BG = pygame.transform.scale(SPACE_IMAGE, (WIDTH, HEIGHT))
25
26# Формируем объект границы
27BORDER = pygame.Rect(WIDTH//2 - 2, 0, 4, HEIGHT)
28
29# Загружаем изображение красного корабля
30RED_SPACESHIP_IMAGE = pygame.image.load(
31 os.path.join('./assets', 'spaceship_red.png'))
32# Разворачиваем изображение в нужном направлении
33RED_SPACESHIP = pygame.transform.rotate(pygame.transform.scale(
34 RED_SPACESHIP_IMAGE, (SPACESHIP_WIDTH, SPACESHIP_HEIGHT)), 90)
35
36# Загружаем изображение желтого корабля
37YELLOW_SPACESHIP_IMAGE = pygame.image.load(
38 os.path.join('./assets', 'spaceship_yellow.png'))
39# Разворачиваем изображение в нужном направлении
40YELLOW_SPACESHIP = pygame.transform.rotate(pygame.transform.scale(
41 YELLOW_SPACESHIP_IMAGE, (SPACESHIP_WIDTH, SPACESHIP_HEIGHT)), 270)
42
43# Создаем два объекта/прямоугольника
44red = pygame.Rect(100, 150, SPACESHIP_WIDTH, SPACESHIP_HEIGHT)
45yellow = pygame.Rect(500, 150, SPACESHIP_WIDTH, SPACESHIP_HEIGHT)
46
47# Запускаем бесконечный цикл программы
48# Это делается чтобы программа не завершалась и постоянно рисовала новые кадры игры
49while True:
50 # Рисуем изображение на заднем фоне
51 screen.blit(SPACE_BG, (0, 0))
52
53 # Рисуем прямоугольник
54 pygame.draw.rect(screen, "white", BORDER)
55
56 # Рисуем корабли
57 screen.blit(YELLOW_SPACESHIP, (yellow.x, yellow.y))
58 screen.blit(RED_SPACESHIP, (red.x, red.y))
59
60 # Постоянно проверяем события игры и если присутствует событие Выход - останавливаем игру.
61 for event in pygame.event.get():
62 if event.type == pygame.QUIT:
63 pygame.quit()
64
65 # Обновляем кадры игры
66 pygame.display.update()
Движение игроков
Теперь оживим наши корабли.
К блоку констант добавьте новую переменную VELOCITY. Данная переменная, как можно предположить из названия, задает скорость кораблей.
1# Скорость корабля
2VELOCITY = 1
Теперь напишем функцию движения красного корабля.
1# Функция движения красного корабля
2def red_handle_movement(keys_pressed, red):
3 # Движение ВЛЕВО
4 if keys_pressed[pygame.K_a] and red.x - VELOCITY > 0:
5 red.x -= VELOCITY
6 # Движение ВПРАВО (запрещаем двигаться вправо дальше чем граница игроков)
7 if keys_pressed[pygame.K_d] and red.x + VELOCITY + red.width < BORDER.x:
8 red.x += VELOCITY
9 # Движение ВВЕРХ (запрещаем подниматься выше 0 по координате y)
10 if keys_pressed[pygame.K_w] and red.y - VELOCITY > 0:
11 red.y -= VELOCITY
12 # Движение ВНИЗ (запрещаем опускаться ниже чем высота экрана за вычетом высоты корабля и дополнительных 15 для отступа)
13 if keys_pressed[pygame.K_s] and red.y + VELOCITY + red.height < HEIGHT - 15:
14 red.y += VELOCITY
Первым аргументом функция получает специальный объект справочник нажатых клавишей. Вторым аргументом функция получает объект Rect красного корабля.
Теперь добавим функцию для желтого корабля:
1# Функция движения желтого корабля
2def yellow_handle_movement(keys_pressed, yellow):
3 # Движение ВЛЕВО (запрещаем пересекать границу игроков)
4 if keys_pressed[pygame.K_LEFT] and yellow.x - VELOCITY > BORDER.x + BORDER.width:
5 yellow.x -= VELOCITY
6 # Движение ВПРАВО
7 if keys_pressed[pygame.K_RIGHT] and yellow.x + VELOCITY + yellow.width < WIDTH:
8 yellow.x += VELOCITY
9 # Движение ВВЕРХ
10 if keys_pressed[pygame.K_UP] and yellow.y - VELOCITY > 0:
11 yellow.y -= VELOCITY
12 # Движение ВНИЗ
13 if keys_pressed[pygame.K_DOWN] and yellow.y + VELOCITY + yellow.height < HEIGHT - 15:
14 yellow.y += VELOCITY
В данных функциях мы проверяем нажатую клавишу (Для красного игрока мы проверяем английские клавиши WASD, для желтого игрока клавиши стрелки), и в зависимости от нажатой клавиши, изменяем нужную координату объекта на скорость корабля (VELOCITY).
Отлично, осталось вызвать эти функции в цикле. Добавьте в бесконечный цикл отрисовки следующие строчки:
1# Узнаем нажатие клавишей
2 keys_pressed = pygame.key.get_pressed()
3 # Выполняем установку координат кораблей
4 red_handle_movement(keys_pressed, red)
5 yellow_handle_movement(keys_pressed, yellow)
В бесконечном цикле, мы получаем специальный список нажатых клавишей и вызываем функции движения для каждого корабля.
Запустите программу, должно получиться вот так:

Промежуточный результат #4
Работает:
- Кнопка закрыть/свернуть
- Отображается задний фон
- Разделитель экрана
- Отрисовка игроков
- Движение игроков
1# Подключаем игровой движок Pygame
2import pygame
3# Подключаем модуль для работы с файловой системой
4import os
5
6# Подготавливаем необходимые модули Pygame
7pygame.init()
8
9### Константы ###
10# Константы размера окна
11WIDTH = 600
12HEIGHT = 300
13# Размеры корабля
14SPACESHIP_WIDTH = 55
15SPACESHIP_HEIGHT = 40
16# Скорость корабля
17VELOCITY = 1
18
19# Задаем размеры игрового окна
20screen = pygame.display.set_mode((WIDTH, HEIGHT))
21
22# Загружаем изображение в память
23SPACE_IMAGE = pygame.image.load(os.path.join('./assets', 'space.jpg'))
24
25# Создаем объект фона с разрешением окна
26SPACE_BG = pygame.transform.scale(SPACE_IMAGE, (WIDTH, HEIGHT))
27
28# Формируем объект границы
29BORDER = pygame.Rect(WIDTH//2 - 2, 0, 4, HEIGHT)
30
31# Загружаем изображение красного корабля
32RED_SPACESHIP_IMAGE = pygame.image.load(
33 os.path.join('./assets', 'spaceship_red.png'))
34# Разворачиваем изображение в нужном направлении
35RED_SPACESHIP = pygame.transform.rotate(pygame.transform.scale(
36 RED_SPACESHIP_IMAGE, (SPACESHIP_WIDTH, SPACESHIP_HEIGHT)), 90)
37
38# Загружаем изображение желтого корабля
39YELLOW_SPACESHIP_IMAGE = pygame.image.load(
40 os.path.join('./assets', 'spaceship_yellow.png'))
41# Разворачиваем изображение в нужном направлении
42YELLOW_SPACESHIP = pygame.transform.rotate(pygame.transform.scale(
43 YELLOW_SPACESHIP_IMAGE, (SPACESHIP_WIDTH, SPACESHIP_HEIGHT)), 270)
44
45# Создаем два объекта/прямоугольника
46red = pygame.Rect(100, 150, SPACESHIP_WIDTH, SPACESHIP_HEIGHT)
47yellow = pygame.Rect(500, 150, SPACESHIP_WIDTH, SPACESHIP_HEIGHT)
48
49# Функция движения красного корабля
50def red_handle_movement(keys_pressed, red):
51 # Движение ВЛЕВО
52 if keys_pressed[pygame.K_a] and red.x - VELOCITY > 0:
53 red.x -= VELOCITY
54 # Движение ВПРАВО (запрещаем пересекать границу игроков)
55 if keys_pressed[pygame.K_d] and red.x + VELOCITY + red.width < BORDER.x:
56 red.x += VELOCITY
57 # Движение ВВЕРХ (запрещаем подниматься выше 0 по координате y)
58 if keys_pressed[pygame.K_w] and red.y - VELOCITY > 0:
59 red.y -= VELOCITY
60 # Движение ВНИЗ (запрещаем опускаться ниже чем высота экрана за вычетом высоты корабля и дополнительных 15 для отступа)
61 if keys_pressed[pygame.K_s] and red.y + VELOCITY + red.height < HEIGHT - 15:
62 red.y += VELOCITY
63
64# Функция движения желтого корабля
65def yellow_handle_movement(keys_pressed, yellow):
66 # Движение ВЛЕВО (запрещаем пересекать границу игроков)
67 if keys_pressed[pygame.K_LEFT] and yellow.x - VELOCITY > BORDER.x + BORDER.width:
68 yellow.x -= VELOCITY
69 # Движение ВПРАВО
70 if keys_pressed[pygame.K_RIGHT] and yellow.x + VELOCITY + yellow.width < WIDTH:
71 yellow.x += VELOCITY
72 # Движение ВВЕРХ
73 if keys_pressed[pygame.K_UP] and yellow.y - VELOCITY > 0:
74 yellow.y -= VELOCITY
75 # Движение ВНИЗ
76 if keys_pressed[pygame.K_DOWN] and yellow.y + VELOCITY + yellow.height < HEIGHT - 15:
77 yellow.y += VELOCITY
78
79
80# Запускаем бесконечный цикл программы
81# Это делается чтобы программа не завершалась и постоянно рисовала новые кадры игры
82while True:
83 # Рисуем изображение на заднем фоне
84 screen.blit(SPACE_BG, (0, 0))
85
86 # Рисуем прямоугольник
87 pygame.draw.rect(screen, "white", BORDER)
88
89 # Рисуем корабли
90 screen.blit(YELLOW_SPACESHIP, (yellow.x, yellow.y))
91 screen.blit(RED_SPACESHIP, (red.x, red.y))
92
93 # Постоянно проверяем события игры и если присутствует событие Выход - останавливаем игру.
94 for event in pygame.event.get():
95 if event.type == pygame.QUIT:
96 pygame.quit()
97
98 # Узнаем нажатие клавишей
99 keys_pressed = pygame.key.get_pressed()
100 # Выполняем установку координат кораблей
101 red_handle_movement(keys_pressed, red)
102 yellow_handle_movement(keys_pressed, yellow)
103
104 # Обновляем кадры игры
105 pygame.display.update()
Ограничитель кадров
Сейчас корабли движутся слишком быстро. Это происходит потому, что наши корабли меняют свое положения в зависимости от скорости цикла While. Дело в том что цикл While очень быстрый и такие простые операции могут выполняться до нескольких тысяч раз в секунду. Это означает что скорость игры и отрисовки кадров будет зависеть от производительности процессора. Нам это не подходит. Давайте добавим ограничитель кадров.
Добавьте константу - количество кадров в секунду (frame per second):
1# Количество кадров в секунду
2FPS = 60
Затем создайте специальный объект ограничитель кадров.
1# Ограничитель кадров
2clock = pygame.time.Clock()
И теперь добавьте строчку clock.tick(FPS) сразу после вызова цикла:
1# Запускаем бесконечный цикл программы
2# Это делается чтобы программа не завершалась и постоянно рисовала новые кадры игры
3while True:
4 # Ограничиваем количество кадров игры
5 clock.tick(FPS)
Благодаря этому коду, цикл будет вызываться не чаще чем 60 раз в секунду. Это то, что нам нужно. Сохраните, запустите, проверьте.
Но теперь корабли движутся очень медленно. Все верно, ведь мы так сильно сократили количество проверок нажатых клавиш. Поправить это просто - поднимите значение VELOCITY. Я подниму до 5.
Промежуточный результат #5
Работает:
- Кнопка закрыть/свернуть
- Отображается задний фон
- Разделитель экрана
- Отрисовка игроков
- Движение игроков
- Ограничитель кадров
1# Подключаем игровой движок Pygame
2import pygame
3# Подключаем модуль для работы с файловой системой
4import os
5
6# Подготавливаем необходимые модули Pygame
7pygame.init()
8
9### Константы ###
10# Константы размера окна
11WIDTH = 600
12HEIGHT = 300
13# Размеры корабля
14SPACESHIP_WIDTH = 55
15SPACESHIP_HEIGHT = 40
16# Скорость корабля
17VELOCITY = 5
18# Количество кадров в секунду
19FPS = 60
20
21# Ограничитель кадров
22clock = pygame.time.Clock()
23
24# Задаем размеры игрового окна
25screen = pygame.display.set_mode((WIDTH, HEIGHT))
26
27# Загружаем изображение в память
28SPACE_IMAGE = pygame.image.load(os.path.join('./assets', 'space.jpg'))
29
30# Создаем объект фона с разрешением окна
31SPACE_BG = pygame.transform.scale(SPACE_IMAGE, (WIDTH, HEIGHT))
32
33# Формируем объект границы
34BORDER = pygame.Rect(WIDTH//2 - 2, 0, 4, HEIGHT)
35
36# Загружаем изображение красного корабля
37RED_SPACESHIP_IMAGE = pygame.image.load(
38 os.path.join('./assets', 'spaceship_red.png'))
39# Разворачиваем изображение в нужном направлении
40RED_SPACESHIP = pygame.transform.rotate(pygame.transform.scale(
41 RED_SPACESHIP_IMAGE, (SPACESHIP_WIDTH, SPACESHIP_HEIGHT)), 90)
42
43# Загружаем изображение желтого корабля
44YELLOW_SPACESHIP_IMAGE = pygame.image.load(
45 os.path.join('./assets', 'spaceship_yellow.png'))
46# Разворачиваем изображение в нужном направлении
47YELLOW_SPACESHIP = pygame.transform.rotate(pygame.transform.scale(
48 YELLOW_SPACESHIP_IMAGE, (SPACESHIP_WIDTH, SPACESHIP_HEIGHT)), 270)
49
50# Создаем два объекта/прямоугольника
51red = pygame.Rect(100, 150, SPACESHIP_WIDTH, SPACESHIP_HEIGHT)
52yellow = pygame.Rect(500, 150, SPACESHIP_WIDTH, SPACESHIP_HEIGHT)
53
54# Функция движения красного корабля
55def red_handle_movement(keys_pressed, red):
56 # Движение ВЛЕВО
57 if keys_pressed[pygame.K_a] and red.x - VELOCITY > 0:
58 red.x -= VELOCITY
59 # Движение ВПРАВО (запрещаем пересекать границу игроков)
60 if keys_pressed[pygame.K_d] and red.x + VELOCITY + red.width < BORDER.x:
61 red.x += VELOCITY
62 # Движение ВВЕРХ (запрещаем подниматься выше 0 по координате y)
63 if keys_pressed[pygame.K_w] and red.y - VELOCITY > 0:
64 red.y -= VELOCITY
65 # Движение ВНИЗ (запрещаем опускаться ниже чем высота экрана за вычетом высоты корабля и дополнительных 15 для отступа)
66 if keys_pressed[pygame.K_s] and red.y + VELOCITY + red.height < HEIGHT - 15:
67 red.y += VELOCITY
68
69# Функция движения желтого корабля
70def yellow_handle_movement(keys_pressed, yellow):
71 # Движение ВЛЕВО (запрещаем пересекать границу игроков)
72 if keys_pressed[pygame.K_LEFT] and yellow.x - VELOCITY > BORDER.x + BORDER.width:
73 yellow.x -= VELOCITY
74 # Движение ВПРАВО
75 if keys_pressed[pygame.K_RIGHT] and yellow.x + VELOCITY + yellow.width < WIDTH:
76 yellow.x += VELOCITY
77 # Движение ВВЕРХ
78 if keys_pressed[pygame.K_UP] and yellow.y - VELOCITY > 0:
79 yellow.y -= VELOCITY
80 # Движение ВНИЗ
81 if keys_pressed[pygame.K_DOWN] and yellow.y + VELOCITY + yellow.height < HEIGHT - 15:
82 yellow.y += VELOCITY
83
84
85# Запускаем бесконечный цикл программы
86# Это делается чтобы программа не завершалась и постоянно рисовала новые кадры игры
87while True:
88 # Ограничиваем количество кадров игры
89 clock.tick(FPS)
90
91 # Рисуем изображение на заднем фоне
92 screen.blit(SPACE_BG, (0, 0))
93
94 # Рисуем прямоугольник
95 pygame.draw.rect(screen, "white", BORDER)
96
97 # Рисуем корабли
98 screen.blit(YELLOW_SPACESHIP, (yellow.x, yellow.y))
99 screen.blit(RED_SPACESHIP, (red.x, red.y))
100
101 # Постоянно проверяем события игры и если присутствует событие Выход - останавливаем игру.
102 for event in pygame.event.get():
103 if event.type == pygame.QUIT:
104 pygame.quit()
105
106 # Узнаем нажатие клавишей
107 keys_pressed = pygame.key.get_pressed()
108 # Выполняем установку координат кораблей
109 red_handle_movement(keys_pressed, red)
110 yellow_handle_movement(keys_pressed, yellow)
111
112 # Обновляем кадры игры
113 pygame.display.update()
114
115
Здоровье игроков
Теперь добавим отображение здоровья игроков.
Создайте две переменные для хранения здоровья игроков:
1# Здоровье игроков
2red_health = 10
3yellow_health = 10
Так же к константам добавьте переменную шрифта:
1# Шрифт здоровья
2HEALTH_FONT = pygame.font.SysFont('comicsans', 20)
Отлично. Теперь в бесконечном цикле отрисовки нарисуем текст:
1# Отображаем здоровье на экране
2red_health_text = HEALTH_FONT.render(
3 "Health: " + str(red_health), 1, "white")
4yellow_health_text = HEALTH_FONT.render(
5 "Health: " + str(yellow_health), 1, "white")
6screen.blit(red_health_text, (10, 10))
7screen.blit(yellow_health_text, (WIDTH - red_health_text.get_width() - 10, 10))
Обратите внимание, что рисовать текст здоровья нужно последним, иначе если сначала отрисовать текст, а затем задний фон, то последний просто перекроет текст.
Должно получиться так:

Промежуточный результат #6
Работает:
- Кнопка закрыть/свернуть
- Отображается задний фон
- Разделитель экрана
- Отрисовка игроков
- Движение игроков
- Ограничитель кадров
- Здоровье игроков
1# Подключаем игровой движок Pygame
2import pygame
3# Подключаем модуль для работы с файловой системой
4import os
5
6# Подготавливаем необходимые модули Pygame
7pygame.init()
8
9### Константы ###
10# Константы размера окна
11WIDTH = 600
12HEIGHT = 300
13# Размеры корабля
14SPACESHIP_WIDTH = 55
15SPACESHIP_HEIGHT = 40
16# Скорость корабля
17VELOCITY = 5
18# Количество кадров в секунду
19FPS = 60
20# Шрифт здоровья
21HEALTH_FONT = pygame.font.SysFont('comicsans', 20)
22
23# Ограничитель кадров
24clock = pygame.time.Clock()
25
26# Задаем размеры игрового окна
27screen = pygame.display.set_mode((WIDTH, HEIGHT))
28
29# Загружаем изображение в память
30SPACE_IMAGE = pygame.image.load(os.path.join('./assets', 'space.jpg'))
31
32# Создаем объект фона с разрешением окна
33SPACE_BG = pygame.transform.scale(SPACE_IMAGE, (WIDTH, HEIGHT))
34
35# Формируем объект границы
36BORDER = pygame.Rect(WIDTH//2 - 2, 0, 4, HEIGHT)
37
38# Загружаем изображение красного корабля
39RED_SPACESHIP_IMAGE = pygame.image.load(
40 os.path.join('./assets', 'spaceship_red.png'))
41# Разворачиваем изображение в нужном направлении
42RED_SPACESHIP = pygame.transform.rotate(pygame.transform.scale(
43 RED_SPACESHIP_IMAGE, (SPACESHIP_WIDTH, SPACESHIP_HEIGHT)), 90)
44
45# Загружаем изображение желтого корабля
46YELLOW_SPACESHIP_IMAGE = pygame.image.load(
47 os.path.join('./assets', 'spaceship_yellow.png'))
48# Разворачиваем изображение в нужном направлении
49YELLOW_SPACESHIP = pygame.transform.rotate(pygame.transform.scale(
50 YELLOW_SPACESHIP_IMAGE, (SPACESHIP_WIDTH, SPACESHIP_HEIGHT)), 270)
51
52# Создаем два объекта/прямоугольника
53red = pygame.Rect(100, 150, SPACESHIP_WIDTH, SPACESHIP_HEIGHT)
54yellow = pygame.Rect(500, 150, SPACESHIP_WIDTH, SPACESHIP_HEIGHT)
55
56# Здоровье игроков
57red_health = 10
58yellow_health = 10
59
60# Функция движения красного корабля
61def red_handle_movement(keys_pressed, red):
62 # Движение ВЛЕВО
63 if keys_pressed[pygame.K_a] and red.x - VELOCITY > 0:
64 red.x -= VELOCITY
65 # Движение ВПРАВО (запрещаем пересекать границу игроков)
66 if keys_pressed[pygame.K_d] and red.x + VELOCITY + red.width < BORDER.x:
67 red.x += VELOCITY
68 # Движение ВВЕРХ (запрещаем подниматься выше 0 по координате y)
69 if keys_pressed[pygame.K_w] and red.y - VELOCITY > 0:
70 red.y -= VELOCITY
71 # Движение ВНИЗ (запрещаем опускаться ниже чем высота экрана за вычетом высоты корабля и дополнительных 15 для отступа)
72 if keys_pressed[pygame.K_s] and red.y + VELOCITY + red.height < HEIGHT - 15:
73 red.y += VELOCITY
74
75# Функция движения желтого корабля
76def yellow_handle_movement(keys_pressed, yellow):
77 # Движение ВЛЕВО (запрещаем пересекать границу игроков)
78 if keys_pressed[pygame.K_LEFT] and yellow.x - VELOCITY > BORDER.x + BORDER.width:
79 yellow.x -= VELOCITY
80 # Движение ВПРАВО
81 if keys_pressed[pygame.K_RIGHT] and yellow.x + VELOCITY + yellow.width < WIDTH:
82 yellow.x += VELOCITY
83 # Движение ВВЕРХ
84 if keys_pressed[pygame.K_UP] and yellow.y - VELOCITY > 0:
85 yellow.y -= VELOCITY
86 # Движение ВНИЗ
87 if keys_pressed[pygame.K_DOWN] and yellow.y + VELOCITY + yellow.height < HEIGHT - 15:
88 yellow.y += VELOCITY
89
90
91# Запускаем бесконечный цикл программы
92# Это делается чтобы программа не завершалась и постоянно рисовала новые кадры игры
93while True:
94 # Ограничиваем количество кадров игры
95 clock.tick(FPS)
96
97 # Рисуем изображение на заднем фоне
98 screen.blit(SPACE_BG, (0, 0))
99
100 # Рисуем прямоугольник
101 pygame.draw.rect(screen, "white", BORDER)
102
103 # Рисуем корабли
104 screen.blit(YELLOW_SPACESHIP, (yellow.x, yellow.y))
105 screen.blit(RED_SPACESHIP, (red.x, red.y))
106
107 # Отображаем здоровье на экране
108 red_health_text = HEALTH_FONT.render(
109 "Health: " + str(red_health), 1, "white")
110 yellow_health_text = HEALTH_FONT.render(
111 "Health: " + str(yellow_health), 1, "white")
112 screen.blit(red_health_text, (10, 10))
113 screen.blit(yellow_health_text, (WIDTH - red_health_text.get_width() - 10, 10))
114
115 # Постоянно проверяем события игры и если присутствует событие Выход - останавливаем игру.
116 for event in pygame.event.get():
117 if event.type == pygame.QUIT:
118 pygame.quit()
119
120 # Узнаем нажатие клавишей
121 keys_pressed = pygame.key.get_pressed()
122 # Выполняем установку координат кораблей
123 red_handle_movement(keys_pressed, red)
124 yellow_handle_movement(keys_pressed, yellow)
125
126 # Обновляем кадры игры
127 pygame.display.update()
Выстрелы
Наконец добавим выстрелы. Выстрелы будет работать следующий образом. Каждый игрок может выпустить до трех пуль за раз. Пока они не попадут в цель или не покинут экран, игрок не сможет сделать дополнительный выстрел. При попадании пули у игрока будет отниматься здоровье.
Создайте переменные для хранения выпущенных пуль, переменную для максимального количества выпущенных пуль, а так же переменную - скорость пули:
1# Хранение выпущенных пуль
2red_bullets = []
3yellow_bullets = []
4# Макс. выпущенных пуль
5MAX_BULLETS = 3
6# Скорость пули
7BULLET_VEL = 7
Так же создайте два новых пользовательских события - попадание в красного и попадание в желтого:
1# Пользовательские события попаданий
2YELLOW_HIT = pygame.USEREVENT + 1
3RED_HIT = pygame.USEREVENT + 2
Плюс один и плюс два просто позволяют создать новые коды событий, нам они понадобятся ниже.
В блок, где мы перебирали все события игры, и искали событие закрытия программы, чтобы отобразить кнопку закрыть, добавьте следующий код:
1# Постоянно проверяем события игры и если присутствует событие Выход - останавливаем игру.
2for event in pygame.event.get():
3 if event.type == pygame.QUIT:
4 pygame.quit()
5
6 # Если произошло событие нажатия клавиши
7 if event.type == pygame.KEYDOWN:
8 # И нажали клавишу Пробел, а так же если длина листа выпущенных пуль красного меньше минимального
9 if event.key == pygame.K_SPACE and len(red_bullets) < MAX_BULLETS:
10 # Создаем объект прямоугольника для Пули
11 bullet = pygame.Rect(
12 red.x + red.width, red.y + red.height//2 - 2, 10, 5)
13 # Добавляем выпущенную пулю красному
14 red_bullets.append(bullet)
15
16 # Если нажали клавишу Enter, создаем выпущенную пулю желтому игроку
17 if event.key == pygame.K_RETURN and len(yellow_bullets) < MAX_BULLETS:
18 # Создаем объект прямоугольника для Пули
19 bullet = pygame.Rect(
20 yellow.x, yellow.y + yellow.height//2 - 2, 10, 5)
21 # Добавляем выпущенную пулю желтому
22 yellow_bullets.append(bullet)
Благодаря этому коду, мы программно выпускаем пули у игроков и сохраняем выпущенные пули в соответствующих списках.
Теперь нужно обработать попадания и вылет пуль за экран.
Напишите следующую функцию:
1# Обработка выпущенных пуль
2def handle_bullets(yellow_bullets, red_bullets, yellow, red):
3 # Перебираем все пули красного
4 for bullet in red_bullets:
5 # Двигаем пулю вправо
6 bullet.x += BULLET_VEL
7 # Если пуля задевает желтого игрока
8 if yellow.colliderect(bullet):
9 # Вызываем пользовательское событие попадание в Желтого
10 pygame.event.post(pygame.event.Event(YELLOW_HIT))
11 # Удаляем текущую пулю
12 red_bullets.remove(bullet)
13 # Удаляем пулю если она вышла за экран
14 elif bullet.x > WIDTH:
15 red_bullets.remove(bullet)
16
17 # Перебираем все пули желтого
18 for bullet in yellow_bullets:
19 # Двигаем пулю влево
20 bullet.x -= BULLET_VEL
21 # Если пуля задевает красного игрока
22 if red.colliderect(bullet):
23 # Вызываем пользовательское событие попадание в Красного
24 pygame.event.post(pygame.event.Event(RED_HIT))
25 # Удаляем текущую пулю
26 yellow_bullets.remove(bullet)
27 # Удаляем пулю если она вышла за экран
28 elif bullet.x < 0:
29 yellow_bullets.remove(bullet)
Данная функция передвигает выстрелы, проверяет вылеты пули за экран, при этом удаляя пулю из листа, а так же проверяет попадание пули в корабли (метод colliderect) и если попадание случилось - вызывает соответствующее пользовательское событие.
Отлично, мы сделали выпуск пуль по нажатиям на клавиши, мы сделали обработку попаданий, но пуль все еще нет на экране. Пора отрисовать их.
Добавьте в бесконечный цикл следующий код:
1# Перебираем пули красного и рисуем каждый кадр
2for bullet in red_bullets:
3 pygame.draw.rect(screen, "red", bullet)
4# Перебираем пули желтого и рисуем каждый кадр
5for bullet in yellow_bullets:
6 pygame.draw.rect(screen, "yellow", bullet)
Каждый кадр мы проверяем наличие пуль в листе и рисуем их.
Ура! Теперь наши корабли стреляют!
Промежуточный результат #7
Работает:
- Кнопка закрыть/свернуть
- Отображается задний фон
- Разделитель экрана
- Отрисовка игроков
- Движение игроков
- Ограничитель кадров
- Здоровье игроков
- Выстрелы кораблей
1# Подключаем игровой движок Pygame
2import pygame
3# Подключаем модуль для работы с файловой системой
4import os
5
6# Подготавливаем необходимые модули Pygame
7pygame.init()
8
9### Константы ###
10# Константы размера окна
11WIDTH = 600
12HEIGHT = 300
13# Размеры корабля
14SPACESHIP_WIDTH = 55
15SPACESHIP_HEIGHT = 40
16# Скорость корабля
17VELOCITY = 5
18# Количество кадров в секунду
19FPS = 60
20# Шрифт здоровья
21HEALTH_FONT = pygame.font.SysFont('comicsans', 20)
22# Пользовательские события попаданий
23YELLOW_HIT = pygame.USEREVENT + 1
24RED_HIT = pygame.USEREVENT + 2
25
26# Ограничитель кадров
27clock = pygame.time.Clock()
28
29# Задаем размеры игрового окна
30screen = pygame.display.set_mode((WIDTH, HEIGHT))
31
32# Загружаем изображение в память
33SPACE_IMAGE = pygame.image.load(os.path.join('./assets', 'space.jpg'))
34
35# Создаем объект фона с разрешением окна
36SPACE_BG = pygame.transform.scale(SPACE_IMAGE, (WIDTH, HEIGHT))
37
38# Формируем объект границы
39BORDER = pygame.Rect(WIDTH//2 - 2, 0, 4, HEIGHT)
40
41# Загружаем изображение красного корабля
42RED_SPACESHIP_IMAGE = pygame.image.load(
43 os.path.join('./assets', 'spaceship_red.png'))
44# Разворачиваем изображение в нужном направлении
45RED_SPACESHIP = pygame.transform.rotate(pygame.transform.scale(
46 RED_SPACESHIP_IMAGE, (SPACESHIP_WIDTH, SPACESHIP_HEIGHT)), 90)
47
48# Загружаем изображение желтого корабля
49YELLOW_SPACESHIP_IMAGE = pygame.image.load(
50 os.path.join('./assets', 'spaceship_yellow.png'))
51# Разворачиваем изображение в нужном направлении
52YELLOW_SPACESHIP = pygame.transform.rotate(pygame.transform.scale(
53 YELLOW_SPACESHIP_IMAGE, (SPACESHIP_WIDTH, SPACESHIP_HEIGHT)), 270)
54
55# Создаем два объекта/прямоугольника
56red = pygame.Rect(100, 150, SPACESHIP_WIDTH, SPACESHIP_HEIGHT)
57yellow = pygame.Rect(500, 150, SPACESHIP_WIDTH, SPACESHIP_HEIGHT)
58
59# Здоровье игроков
60red_health = 10
61yellow_health = 10
62
63# Хранение выпущенных пуль
64red_bullets = []
65yellow_bullets = []
66# Макс. выпущенных пуль
67MAX_BULLETS = 3
68# Скорость пули
69BULLET_VEL = 7
70
71# Функция движения красного корабля
72def red_handle_movement(keys_pressed, red):
73 # Движение ВЛЕВО
74 if keys_pressed[pygame.K_a] and red.x - VELOCITY > 0:
75 red.x -= VELOCITY
76 # Движение ВПРАВО (запрещаем пересекать границу игроков)
77 if keys_pressed[pygame.K_d] and red.x + VELOCITY + red.width < BORDER.x:
78 red.x += VELOCITY
79 # Движение ВВЕРХ (запрещаем подниматься выше 0 по координате y)
80 if keys_pressed[pygame.K_w] and red.y - VELOCITY > 0:
81 red.y -= VELOCITY
82 # Движение ВНИЗ (запрещаем опускаться ниже чем высота экрана за вычетом высоты корабля и дополнительных 15 для отступа)
83 if keys_pressed[pygame.K_s] and red.y + VELOCITY + red.height < HEIGHT - 15:
84 red.y += VELOCITY
85
86# Функция движения желтого корабля
87def yellow_handle_movement(keys_pressed, yellow):
88 # Движение ВЛЕВО (запрещаем пересекать границу игроков)
89 if keys_pressed[pygame.K_LEFT] and yellow.x - VELOCITY > BORDER.x + BORDER.width:
90 yellow.x -= VELOCITY
91 # Движение ВПРАВО
92 if keys_pressed[pygame.K_RIGHT] and yellow.x + VELOCITY + yellow.width < WIDTH:
93 yellow.x += VELOCITY
94 # Движение ВВЕРХ
95 if keys_pressed[pygame.K_UP] and yellow.y - VELOCITY > 0:
96 yellow.y -= VELOCITY
97 # Движение ВНИЗ
98 if keys_pressed[pygame.K_DOWN] and yellow.y + VELOCITY + yellow.height < HEIGHT - 15:
99 yellow.y += VELOCITY
100
101# Обработка выпущенных пуль
102def handle_bullets(yellow_bullets, red_bullets, yellow, red):
103 # Перебираем все пули красного
104 for bullet in red_bullets:
105 # Двигаем пулю вправо
106 bullet.x += BULLET_VEL
107 # Если пуля задевает желтого игрока
108 if yellow.colliderect(bullet):
109 # Вызываем пользовательское событие попадание в Желтого
110 pygame.event.post(pygame.event.Event(YELLOW_HIT))
111 # Удаляем текущую пулю
112 red_bullets.remove(bullet)
113 # Удаляем пулю если она вышла за экран
114 elif bullet.x > WIDTH:
115 red_bullets.remove(bullet)
116
117 # Перебираем все пули желтого
118 for bullet in yellow_bullets:
119 # Двигаем пулю влево
120 bullet.x -= BULLET_VEL
121 # Если пуля задевает красного игрока
122 if red.colliderect(bullet):
123 # Вызываем пользовательское событие попадание в Красного
124 pygame.event.post(pygame.event.Event(RED_HIT))
125 # Удаляем текущую пулю
126 yellow_bullets.remove(bullet)
127 # Удаляем пулю если она вышла за экран
128 elif bullet.x < 0:
129 yellow_bullets.remove(bullet)
130
131
132# Запускаем бесконечный цикл программы
133# Это делается чтобы программа не завершалась и постоянно рисовала новые кадры игры
134while True:
135 # Ограничиваем количество кадров игры
136 clock.tick(FPS)
137
138 # Рисуем изображение на заднем фоне
139 screen.blit(SPACE_BG, (0, 0))
140
141 # Рисуем прямоугольник
142 pygame.draw.rect(screen, "white", BORDER)
143
144 # Рисуем корабли
145 screen.blit(YELLOW_SPACESHIP, (yellow.x, yellow.y))
146 screen.blit(RED_SPACESHIP, (red.x, red.y))
147
148 # Отображаем здоровье на экране
149 red_health_text = HEALTH_FONT.render(
150 "Health: " + str(red_health), 1, "white")
151 yellow_health_text = HEALTH_FONT.render(
152 "Health: " + str(yellow_health), 1, "white")
153 screen.blit(red_health_text, (10, 10))
154 screen.blit(yellow_health_text, (WIDTH - red_health_text.get_width() - 10, 10))
155
156 # Постоянно проверяем события игры и если присутствует событие Выход - останавливаем игру.
157 for event in pygame.event.get():
158 if event.type == pygame.QUIT:
159 pygame.quit()
160
161 # Если произошло событие нажатия клавиши
162 if event.type == pygame.KEYDOWN:
163 # И нажали клавишу Пробел, а так же если длина листа выпущенных пуль красного меньше минимального
164 if event.key == pygame.K_SPACE and len(red_bullets) < MAX_BULLETS:
165 # Создаем объект прямоугольника для Пули
166 bullet = pygame.Rect(
167 red.x + red.width, red.y + red.height//2 - 2, 10, 5)
168 # Добавляем выпущенную пулю красному
169 red_bullets.append(bullet)
170
171 # Если нажали клавишу Enter, создаем выпущенную пулю желтому игроку
172 if event.key == pygame.K_RETURN and len(yellow_bullets) < MAX_BULLETS:
173 # Создаем объект прямоугольника для Пули
174 bullet = pygame.Rect(
175 yellow.x, yellow.y + yellow.height//2 - 2, 10, 5)
176 # Добавляем выпущенную пулю желтому
177 yellow_bullets.append(bullet)
178
179 # Узнаем нажатие клавишей
180 keys_pressed = pygame.key.get_pressed()
181 # Выполняем установку координат кораблей
182 red_handle_movement(keys_pressed, red)
183 yellow_handle_movement(keys_pressed, yellow)
184
185 # Проверяем столкновения пуль
186 handle_bullets(yellow_bullets, red_bullets, yellow, red)
187
188 # Перебираем пули красного и рисуем каждый кадр
189 for bullet in red_bullets:
190 pygame.draw.rect(screen, "red", bullet)
191 # Перебираем пули желтого и рисуем каждый кадр
192 for bullet in yellow_bullets:
193 pygame.draw.rect(screen, "yellow", bullet)
194
195 # Обновляем кадры игры
196 pygame.display.update()
197
Учет попаданий - Отображение победителя
Теперь нужно при попадании уменьшать здоровье игроков. Ранее мы создали пользовательские события RED_HIT и YELLOW_HIT и при попадании в соответствующего игрока вызвали соответствующее событие. Теперь достаточно обработать эти события.
Добавьте этот код к участку кода где мы проверяли события нажатия кнопки выйти и нажатия кнопок Space (Пробел) и Enter.
1# Если случилось пользовательское событие RED_HIT отнимаем жизни у Красного
2if event.type == RED_HIT:
3 red_health -= 1
4
5# Если случилось пользовательское событие YELLOW_HIT отнимаем жизни у Желтого
6if event.type == YELLOW_HIT:
7 yellow_health -= 1
Если случилось пользовательское событие RED_HIT отнимаем жизни у Красного, если событие YELLOW_HIT отнимаем жизни у Желтого. Думаю теперь стало понятно для чего мы делали пользовательские события. Проверьте. Теперь здоровье должно отниматься, и визуально тоже.
Сейчас здоровье может уходить в минус. Давайте будем проверять - если здоровье упало до нуля, покажем сообщение - Имя победителя, а затем обнулим игровые счетчики.
Напишите следующую функцию:
1# Функция рисует экран победителя
2def draw_winner(text):
3 # Создаем шрифт для победителя
4 WINNER_FONT = pygame.font.SysFont('comicsans', 60)
5 # Создаем надпись
6 draw_text = WINNER_FONT.render(text, 1, 'white')
7 # Устанавливаем надпись в центре игрового поля
8 screen.blit(draw_text, (WIDTH/2 - draw_text.get_width() /
9 2, HEIGHT/2 - draw_text.get_height()/2))
10
11 # Обновляем кадр игры
12 pygame.display.update()
13 # Задержка после победы
14 pygame.time.delay(2000)
Эта функция позволит нарисовать имя победителя по центру экрана, а так же сделать паузы игры на две секунды чтобы игроки не могли управлять игрой в момент отображения победителя.
Теперь в секции бесконечного цикла добавьте этот код:
1# Если здоровье упало до нуля, рисуем имя победителя.
2winner_text = ""
3if red_health <= 0:
4 winner_text = "Yellow Wins!"
5
6if yellow_health <= 0:
7 winner_text = "Red Wins!"
8
9if winner_text != "":
10 draw_winner(winner_text)
11 # Обнуляем пули
12 red_bullets.clear()
13 yellow_bullets.clear()
14 # Восстанавливаем здоровье
15 red_health = 10
16 yellow_health = 10
Каждый кадр игры мы проверяем, не опустился ли показатель здоровья одного из игроков до нуля и если это случилось, рисуем имя победителя, затем делаем паузу в две секунды, затем обнуляем все показатели игры - выстрелы и здоровье.
Поздравляю - база игры готова!

Промежуточный результат #8
Работает:
- Кнопка закрыть/свернуть
- Отображается задний фон
- Разделитель экрана
- Отрисовка игроков
- Движение игроков
- Ограничитель кадров
- Здоровье игроков
- Выстрелы кораблей
- Экран победителя и обнуление показателей
1# Подключаем игровой движок Pygame
2import pygame
3# Подключаем модуль для работы с файловой системой
4import os
5
6# Подготавливаем необходимые модули Pygame
7pygame.init()
8
9### Константы ###
10# Константы размера окна
11WIDTH = 600
12HEIGHT = 300
13# Размеры корабля
14SPACESHIP_WIDTH = 55
15SPACESHIP_HEIGHT = 40
16# Скорость корабля
17VELOCITY = 5
18# Количество кадров в секунду
19FPS = 60
20# Шрифт здоровья
21HEALTH_FONT = pygame.font.SysFont('comicsans', 20)
22# Пользовательские события попаданий
23YELLOW_HIT = pygame.USEREVENT + 1
24RED_HIT = pygame.USEREVENT + 2
25
26# Ограничитель кадров
27clock = pygame.time.Clock()
28
29# Задаем размеры игрового окна
30screen = pygame.display.set_mode((WIDTH, HEIGHT))
31
32# Загружаем изображение в память
33SPACE_IMAGE = pygame.image.load(os.path.join('./assets', 'space.jpg'))
34
35# Создаем объект фона с разрешением окна
36SPACE_BG = pygame.transform.scale(SPACE_IMAGE, (WIDTH, HEIGHT))
37
38# Формируем объект границы
39BORDER = pygame.Rect(WIDTH//2 - 2, 0, 4, HEIGHT)
40
41# Загружаем изображение красного корабля
42RED_SPACESHIP_IMAGE = pygame.image.load(
43 os.path.join('./assets', 'spaceship_red.png'))
44# Разворачиваем изображение в нужном направлении
45RED_SPACESHIP = pygame.transform.rotate(pygame.transform.scale(
46 RED_SPACESHIP_IMAGE, (SPACESHIP_WIDTH, SPACESHIP_HEIGHT)), 90)
47
48# Загружаем изображение желтого корабля
49YELLOW_SPACESHIP_IMAGE = pygame.image.load(
50 os.path.join('./assets', 'spaceship_yellow.png'))
51# Разворачиваем изображение в нужном направлении
52YELLOW_SPACESHIP = pygame.transform.rotate(pygame.transform.scale(
53 YELLOW_SPACESHIP_IMAGE, (SPACESHIP_WIDTH, SPACESHIP_HEIGHT)), 270)
54
55# Создаем два объекта/прямоугольника
56red = pygame.Rect(100, 150, SPACESHIP_WIDTH, SPACESHIP_HEIGHT)
57yellow = pygame.Rect(500, 150, SPACESHIP_WIDTH, SPACESHIP_HEIGHT)
58
59# Здоровье игроков
60red_health = 10
61yellow_health = 10
62
63# Хранение выпущенных пуль
64red_bullets = []
65yellow_bullets = []
66# Макс. выпущенных пуль
67MAX_BULLETS = 3
68# Скорость пули
69BULLET_VEL = 7
70
71# Функция движения красного корабля
72def red_handle_movement(keys_pressed, red):
73 # Движение ВЛЕВО
74 if keys_pressed[pygame.K_a] and red.x - VELOCITY > 0:
75 red.x -= VELOCITY
76 # Движение ВПРАВО (запрещаем пересекать границу игроков)
77 if keys_pressed[pygame.K_d] and red.x + VELOCITY + red.width < BORDER.x:
78 red.x += VELOCITY
79 # Движение ВВЕРХ (запрещаем подниматься выше 0 по координате y)
80 if keys_pressed[pygame.K_w] and red.y - VELOCITY > 0:
81 red.y -= VELOCITY
82 # Движение ВНИЗ (запрещаем опускаться ниже чем высота экрана за вычетом высоты корабля и дополнительных 15 для отступа)
83 if keys_pressed[pygame.K_s] and red.y + VELOCITY + red.height < HEIGHT - 15:
84 red.y += VELOCITY
85
86# Функция движения желтого корабля
87def yellow_handle_movement(keys_pressed, yellow):
88 # Движение ВЛЕВО (запрещаем пересекать границу игроков)
89 if keys_pressed[pygame.K_LEFT] and yellow.x - VELOCITY > BORDER.x + BORDER.width:
90 yellow.x -= VELOCITY
91 # Движение ВПРАВО
92 if keys_pressed[pygame.K_RIGHT] and yellow.x + VELOCITY + yellow.width < WIDTH:
93 yellow.x += VELOCITY
94 # Движение ВВЕРХ
95 if keys_pressed[pygame.K_UP] and yellow.y - VELOCITY > 0:
96 yellow.y -= VELOCITY
97 # Движение ВНИЗ
98 if keys_pressed[pygame.K_DOWN] and yellow.y + VELOCITY + yellow.height < HEIGHT - 15:
99 yellow.y += VELOCITY
100
101# Обработка выпущенных пуль
102def handle_bullets(yellow_bullets, red_bullets, yellow, red):
103 # Перебираем все пули красного
104 for bullet in red_bullets:
105 # Двигаем пулю вправо
106 bullet.x += BULLET_VEL
107 # Если пуля задевает желтого игрока
108 if yellow.colliderect(bullet):
109 # Вызываем пользовательское событие попадание в Желтого
110 pygame.event.post(pygame.event.Event(YELLOW_HIT))
111 # Удаляем текущую пулю
112 red_bullets.remove(bullet)
113 # Удаляем пулю если она вышла за экран
114 elif bullet.x > WIDTH:
115 red_bullets.remove(bullet)
116
117 # Перебираем все пули желтого
118 for bullet in yellow_bullets:
119 # Двигаем пулю влево
120 bullet.x -= BULLET_VEL
121 # Если пуля задевает красного игрока
122 if red.colliderect(bullet):
123 # Вызываем пользовательское событие попадание в Красного
124 pygame.event.post(pygame.event.Event(RED_HIT))
125 # Удаляем текущую пулю
126 yellow_bullets.remove(bullet)
127 # Удаляем пулю если она вышла за экран
128 elif bullet.x < 0:
129 yellow_bullets.remove(bullet)
130
131# Функция рисует экран победителя
132def draw_winner(text):
133 # Создаем шрифт для победителя
134 WINNER_FONT = pygame.font.SysFont('comicsans', 60)
135 # Создаем надпись
136 draw_text = WINNER_FONT.render(text, 1, 'white')
137 # Устанавливаем надпись в центре игрового поля
138 screen.blit(draw_text, (WIDTH/2 - draw_text.get_width() /
139 2, HEIGHT/2 - draw_text.get_height()/2))
140
141 # Обновляем кадр игры
142 pygame.display.update()
143 # Задержка после победы
144 pygame.time.delay(2000)
145
146# Запускаем бесконечный цикл программы
147# Это делается чтобы программа не завершалась и постоянно рисовала новые кадры игры
148while True:
149 # Ограничиваем количество кадров игры
150 clock.tick(FPS)
151
152 # Рисуем изображение на заднем фоне
153 screen.blit(SPACE_BG, (0, 0))
154
155 # Рисуем прямоугольник
156 pygame.draw.rect(screen, "white", BORDER)
157
158 # Рисуем корабли
159 screen.blit(YELLOW_SPACESHIP, (yellow.x, yellow.y))
160 screen.blit(RED_SPACESHIP, (red.x, red.y))
161
162 # Отображаем здоровье на экране
163 red_health_text = HEALTH_FONT.render(
164 "Health: " + str(red_health), 1, "white")
165 yellow_health_text = HEALTH_FONT.render(
166 "Health: " + str(yellow_health), 1, "white")
167 screen.blit(red_health_text, (10, 10))
168 screen.blit(yellow_health_text, (WIDTH - red_health_text.get_width() - 10, 10))
169
170 # Постоянно проверяем события игры и если присутствует событие Выход - останавливаем игру.
171 for event in pygame.event.get():
172 if event.type == pygame.QUIT:
173 pygame.quit()
174
175 # Если случилось пользовательское событие RED_HIT отнимаем жизни у Красного
176 if event.type == RED_HIT:
177 red_health -= 1
178
179 # Если случилось пользовательское событие YELLOW_HIT отнимаем жизни у Желтого
180 if event.type == YELLOW_HIT:
181 yellow_health -= 1
182
183 # Если произошло событие нажатия клавиши
184 if event.type == pygame.KEYDOWN:
185 # И нажали клавишу Пробел, а так же если длина листа выпущенных пуль красного меньше минимального
186 if event.key == pygame.K_SPACE and len(red_bullets) < MAX_BULLETS:
187 # Создаем объект прямоугольника для Пули
188 bullet = pygame.Rect(
189 red.x + red.width, red.y + red.height//2 - 2, 10, 5)
190 # Добавляем выпущенную пулю красному
191 red_bullets.append(bullet)
192
193 # Если нажали клавишу Enter, создаем выпущенную пулю желтому игроку
194 if event.key == pygame.K_RETURN and len(yellow_bullets) < MAX_BULLETS:
195 # Создаем объект прямоугольника для Пули
196 bullet = pygame.Rect(
197 yellow.x, yellow.y + yellow.height//2 - 2, 10, 5)
198 # Добавляем выпущенную пулю желтому
199 yellow_bullets.append(bullet)
200
201 # Узнаем нажатие клавишей
202 keys_pressed = pygame.key.get_pressed()
203 # Выполняем установку координат кораблей
204 red_handle_movement(keys_pressed, red)
205 yellow_handle_movement(keys_pressed, yellow)
206
207 # Проверяем столкновения пуль
208 handle_bullets(yellow_bullets, red_bullets, yellow, red)
209
210 # Перебираем пули красного и рисуем каждый кадр
211 for bullet in red_bullets:
212 pygame.draw.rect(screen, "red", bullet)
213 # Перебираем пули желтого и рисуем каждый кадр
214 for bullet in yellow_bullets:
215 pygame.draw.rect(screen, "yellow", bullet)
216
217 # Если здоровье упало до нуля, рисуем имя победителя.
218 winner_text = ""
219 if red_health <= 0:
220 winner_text = "Yellow Wins!"
221
222 if yellow_health <= 0:
223 winner_text = "Red Wins!"
224
225 if winner_text != "":
226 draw_winner(winner_text)
227 # Обнуляем пули
228 red_bullets.clear()
229 yellow_bullets.clear()
230 # Восстанавливаем здоровье
231 red_health = 10
232 yellow_health = 10
233
234 # Обновляем кадры игры
235 pygame.display.update()
Звуки
Стрелять в тишине кажется странным, поэтому последнее, что мы сделаем это добавим звуки в игру.
Скачайте два звука grenade.mp3 и silencer.mp3 по этой ссылке и положите их в папку assets.
В самом верху нашего кода, там где импортировали модули, добавьте строчку (секция Подготавливаем необходимые модули Pygame):
1pygame.mixer.init()
Данная строчка инициализирует модуль работы со звуками.
Теперь подключим два наших звука к игре.
1# Подключаем звуки к игре
2# Звук попадания
3BULLET_HIT_SOUND = pygame.mixer.Sound('./assets/grenade.mp3')
4# Звук выстрела
5BULLET_FIRE_SOUND = pygame.mixer.Sound('./assets/silencer.mp3')
Теперь необходимо расставить нужные звуки в нужных местах. Добавьте строчку BULLET_HIT_SOUND.play() в местах где мы отнимаем здоровье (обрабатываем попадание)
1# Если случилось пользовательское событие RED_HIT отнимаем жизни у Красного
2if event.type == RED_HIT:
3 red_health -= 1
4 # Звук попадания
5 BULLET_HIT_SOUND.play()
6
7# Если случилось пользовательское событие YELLOW_HIT отнимаем жизни у Желтого
8if event.type == YELLOW_HIT:
9 yellow_health -= 1
10 # Звук попадания
11 BULLET_HIT_SOUND.play()
Так же добавьте строчку BULLET_FIRE_SOUND.play() в местах где мы создаем пули при нажатии кнопок:
1# Если произошло событие нажатия клавиши
2if event.type == pygame.KEYDOWN:
3 # И нажали клавишу Пробел, а так же если длина листа выпущенных пуль красного меньше минимального
4 if event.key == pygame.K_SPACE and len(red_bullets) < MAX_BULLETS:
5 # Создаем объект прямоугольника для Пули
6 bullet = pygame.Rect(
7 red.x + red.width, red.y + red.height//2 - 2, 10, 5)
8 # Добавляем выпущенную пулю красному
9 red_bullets.append(bullet)
10 # Звук выстрела
11 BULLET_FIRE_SOUND.play()
12
13 # Если нажали клавишу Enter, создаем выпущенную пулю желтому игроку
14 if event.key == pygame.K_RETURN and len(yellow_bullets) < MAX_BULLETS:
15 # Создаем объект прямоугольника для Пули
16 bullet = pygame.Rect(
17 yellow.x, yellow.y + yellow.height//2 - 2, 10, 5)
18 # Добавляем выпущенную пулю желтому
19 yellow_bullets.append(bullet)
20 # Звук выстрела
21 BULLET_FIRE_SOUND.play()
Так намного лучше! Игра заиграла новыми красками!
Итоговый результат
Работает:
- Кнопка закрыть/свернуть
- Отображается задний фон
- Разделитель экрана
- Отрисовка игроков
- Движение игроков
- Ограничитель кадров
- Здоровье игроков
- Выстрелы кораблей
- Звуки выстрелов и попаданий
1# Подключаем игровой движок Pygame
2import pygame
3# Подключаем модуль для работы с файловой системой
4import os
5
6# Подготавливаем необходимые модули Pygame
7pygame.init()
8pygame.mixer.init()
9
10# Подключаем звуки к игре
11# Звук попадания
12BULLET_HIT_SOUND = pygame.mixer.Sound('./assets/grenade.mp3')
13# Звук выстрела
14BULLET_FIRE_SOUND = pygame.mixer.Sound('./assets/silencer.mp3')
15
16### Константы ###
17# Константы размера окна
18WIDTH = 600
19HEIGHT = 300
20# Размеры корабля
21SPACESHIP_WIDTH = 55
22SPACESHIP_HEIGHT = 40
23# Скорость корабля
24VELOCITY = 5
25# Количество кадров в секунду
26FPS = 60
27# Шрифт здоровья
28HEALTH_FONT = pygame.font.SysFont('comicsans', 20)
29# Пользовательские события попаданий
30YELLOW_HIT = pygame.USEREVENT + 1
31RED_HIT = pygame.USEREVENT + 2
32
33# Ограничитель кадров
34clock = pygame.time.Clock()
35
36# Задаем размеры игрового окна
37screen = pygame.display.set_mode((WIDTH, HEIGHT))
38
39# Загружаем изображение в память
40SPACE_IMAGE = pygame.image.load(os.path.join('./assets', 'space.jpg'))
41
42# Создаем объект фона с разрешением окна
43SPACE_BG = pygame.transform.scale(SPACE_IMAGE, (WIDTH, HEIGHT))
44
45# Формируем объект границы
46BORDER = pygame.Rect(WIDTH//2 - 2, 0, 4, HEIGHT)
47
48# Загружаем изображение красного корабля
49RED_SPACESHIP_IMAGE = pygame.image.load(
50 os.path.join('./assets', 'spaceship_red.png'))
51# Разворачиваем изображение в нужном направлении
52RED_SPACESHIP = pygame.transform.rotate(pygame.transform.scale(
53 RED_SPACESHIP_IMAGE, (SPACESHIP_WIDTH, SPACESHIP_HEIGHT)), 90)
54
55# Загружаем изображение желтого корабля
56YELLOW_SPACESHIP_IMAGE = pygame.image.load(
57 os.path.join('./assets', 'spaceship_yellow.png'))
58# Разворачиваем изображение в нужном направлении
59YELLOW_SPACESHIP = pygame.transform.rotate(pygame.transform.scale(
60 YELLOW_SPACESHIP_IMAGE, (SPACESHIP_WIDTH, SPACESHIP_HEIGHT)), 270)
61
62# Создаем два объекта/прямоугольника
63red = pygame.Rect(100, 150, SPACESHIP_WIDTH, SPACESHIP_HEIGHT)
64yellow = pygame.Rect(500, 150, SPACESHIP_WIDTH, SPACESHIP_HEIGHT)
65
66# Здоровье игроков
67red_health = 10
68yellow_health = 10
69
70# Хранение выпущенных пуль
71red_bullets = []
72yellow_bullets = []
73# Макс. выпущенных пуль
74MAX_BULLETS = 3
75# Скорость пули
76BULLET_VEL = 7
77
78# Функция движения красного корабля
79def red_handle_movement(keys_pressed, red):
80 # Движение ВЛЕВО
81 if keys_pressed[pygame.K_a] and red.x - VELOCITY > 0:
82 red.x -= VELOCITY
83 # Движение ВПРАВО (запрещаем пересекать границу игроков)
84 if keys_pressed[pygame.K_d] and red.x + VELOCITY + red.width < BORDER.x:
85 red.x += VELOCITY
86 # Движение ВВЕРХ (запрещаем подниматься выше 0 по координате y)
87 if keys_pressed[pygame.K_w] and red.y - VELOCITY > 0:
88 red.y -= VELOCITY
89 # Движение ВНИЗ (запрещаем опускаться ниже чем высота экрана за вычетом высоты корабля и дополнительных 15 для отступа)
90 if keys_pressed[pygame.K_s] and red.y + VELOCITY + red.height < HEIGHT - 15:
91 red.y += VELOCITY
92
93# Функция движения желтого корабля
94def yellow_handle_movement(keys_pressed, yellow):
95 # Движение ВЛЕВО (запрещаем пересекать границу игроков)
96 if keys_pressed[pygame.K_LEFT] and yellow.x - VELOCITY > BORDER.x + BORDER.width:
97 yellow.x -= VELOCITY
98 # Движение ВПРАВО
99 if keys_pressed[pygame.K_RIGHT] and yellow.x + VELOCITY + yellow.width < WIDTH:
100 yellow.x += VELOCITY
101 # Движение ВВЕРХ
102 if keys_pressed[pygame.K_UP] and yellow.y - VELOCITY > 0:
103 yellow.y -= VELOCITY
104 # Движение ВНИЗ
105 if keys_pressed[pygame.K_DOWN] and yellow.y + VELOCITY + yellow.height < HEIGHT - 15:
106 yellow.y += VELOCITY
107
108# Обработка выпущенных пуль
109def handle_bullets(yellow_bullets, red_bullets, yellow, red):
110 # Перебираем все пули красного
111 for bullet in red_bullets:
112 # Двигаем пулю вправо
113 bullet.x += BULLET_VEL
114 # Если пуля задевает желтого игрока
115 if yellow.colliderect(bullet):
116 # Вызываем пользовательское событие попадание в Желтого
117 pygame.event.post(pygame.event.Event(YELLOW_HIT))
118 # Удаляем текущую пулю
119 red_bullets.remove(bullet)
120 # Удаляем пулю если она вышла за экран
121 elif bullet.x > WIDTH:
122 red_bullets.remove(bullet)
123
124 # Перебираем все пули желтого
125 for bullet in yellow_bullets:
126 # Двигаем пулю влево
127 bullet.x -= BULLET_VEL
128 # Если пуля задевает красного игрока
129 if red.colliderect(bullet):
130 # Вызываем пользовательское событие попадание в Красного
131 pygame.event.post(pygame.event.Event(RED_HIT))
132 # Удаляем текущую пулю
133 yellow_bullets.remove(bullet)
134 # Удаляем пулю если она вышла за экран
135 elif bullet.x < 0:
136 yellow_bullets.remove(bullet)
137
138# Функция рисует экран победителя
139def draw_winner(text):
140 # Создаем шрифт для победителя
141 WINNER_FONT = pygame.font.SysFont('comicsans', 60)
142 # Создаем надпись
143 draw_text = WINNER_FONT.render(text, 1, 'white')
144 # Устанавливаем надпись в центре игрового поля
145 screen.blit(draw_text, (WIDTH/2 - draw_text.get_width() /
146 2, HEIGHT/2 - draw_text.get_height()/2))
147
148 # Обновляем кадр игры
149 pygame.display.update()
150 # Задержка после победы
151 pygame.time.delay(2000)
152
153# Запускаем бесконечный цикл программы
154# Это делается чтобы программа не завершалась и постоянно рисовала новые кадры игры
155while True:
156 # Ограничиваем количество кадров игры
157 clock.tick(FPS)
158
159 # Рисуем изображение на заднем фоне
160 screen.blit(SPACE_BG, (0, 0))
161
162 # Рисуем прямоугольник
163 pygame.draw.rect(screen, "white", BORDER)
164
165 # Рисуем корабли
166 screen.blit(YELLOW_SPACESHIP, (yellow.x, yellow.y))
167 screen.blit(RED_SPACESHIP, (red.x, red.y))
168
169 # Отображаем здоровье на экране
170 red_health_text = HEALTH_FONT.render(
171 "Health: " + str(red_health), 1, "white")
172 yellow_health_text = HEALTH_FONT.render(
173 "Health: " + str(yellow_health), 1, "white")
174 screen.blit(red_health_text, (10, 10))
175 screen.blit(yellow_health_text, (WIDTH - red_health_text.get_width() - 10, 10))
176
177 # Постоянно проверяем события игры и если присутствует событие Выход - останавливаем игру.
178 for event in pygame.event.get():
179 if event.type == pygame.QUIT:
180 pygame.quit()
181
182 # Если случилось пользовательское событие RED_HIT отнимаем жизни у Красного
183 if event.type == RED_HIT:
184 red_health -= 1
185 # Звук попадания
186 BULLET_HIT_SOUND.play()
187
188 # Если случилось пользовательское событие YELLOW_HIT отнимаем жизни у Желтого
189 if event.type == YELLOW_HIT:
190 yellow_health -= 1
191 # Звук попадания
192 BULLET_HIT_SOUND.play()
193
194 # Если произошло событие нажатия клавиши
195 if event.type == pygame.KEYDOWN:
196 # И нажали клавишу Пробел, а так же если длина листа выпущенных пуль красного меньше минимального
197 if event.key == pygame.K_SPACE and len(red_bullets) < MAX_BULLETS:
198 # Создаем объект прямоугольника для Пули
199 bullet = pygame.Rect(
200 red.x + red.width, red.y + red.height//2 - 2, 10, 5)
201 # Добавляем выпущенную пулю красному
202 red_bullets.append(bullet)
203 # Звук выстрела
204 BULLET_FIRE_SOUND.play()
205
206 # Если нажали клавишу Enter, создаем выпущенную пулю желтому игроку
207 if event.key == pygame.K_RETURN and len(yellow_bullets) < MAX_BULLETS:
208 # Создаем объект прямоугольника для Пули
209 bullet = pygame.Rect(
210 yellow.x, yellow.y + yellow.height//2 - 2, 10, 5)
211 # Добавляем выпущенную пулю желтому
212 yellow_bullets.append(bullet)
213 # Звук выстрела
214 BULLET_FIRE_SOUND.play()
215
216 # Узнаем нажатие клавишей
217 keys_pressed = pygame.key.get_pressed()
218 # Выполняем установку координат кораблей
219 red_handle_movement(keys_pressed, red)
220 yellow_handle_movement(keys_pressed, yellow)
221
222 # Проверяем столкновения пуль
223 handle_bullets(yellow_bullets, red_bullets, yellow, red)
224
225 # Перебираем пули красного и рисуем каждый кадр
226 for bullet in red_bullets:
227 pygame.draw.rect(screen, "red", bullet)
228 # Перебираем пули желтого и рисуем каждый кадр
229 for bullet in yellow_bullets:
230 pygame.draw.rect(screen, "yellow", bullet)
231
232 # Если здоровье упало до нуля, рисуем имя победителя.
233 winner_text = ""
234 if red_health <= 0:
235 winner_text = "Yellow Wins!"
236
237 if yellow_health <= 0:
238 winner_text = "Red Wins!"
239
240 if winner_text != "":
241 draw_winner(winner_text)
242 # Обнуляем пули
243 red_bullets.clear()
244 yellow_bullets.clear()
245 # Восстанавливаем здоровье
246 red_health = 10
247 yellow_health = 10
248
249 # Обновляем кадры игры
250 pygame.display.update()
Поздравляю! Наша игра готова! Теперь можно подумать как ее улучшить. Например, добавить новые звуки, создать возможность собирать powerup-ы и т.д.
Заключение
Библиотека PyGame не предоставит вам инструмента для создания AAA-игры, но для обучения вполне подходящий инструмент. С помощью PyGame легко рисовать фигуры, добавлять на них текстуры, работать с нажатиями клавиш и звуком. Все что нужно для Indie игры. Вот, кстати несколько примеров таких игр.
Если же хочется большего, думаю, стоит присмотреться к игровому движку Godot. Язык программирования Godot Script очень похож на Python, так что разобраться будет не сложно, а проекты там на порядок выше. Вот пример.
Надеюсь данная статься была вам интересна и вы нашли в ней что-то полезное! Удачи!