16.49M
Category: programmingprogramming

Программирование на Python. Урок 11. Взаимодействие объектов

1.

Программирование
на Python
Урок 11
Взаимодействие объектов

2.

Немного повторим
прошлый урок

3.

Программирование на Python | Взаимодействие объектов
Что будет на уроке сегодня?
Добавим спрайт пули в игру
Научимся перемещать пулю в нужном направлении
Настроим взаимодействие и уничтожение мобов
пулями
Добавим правильные звуки в событиях столкновения

4.

Спрайт пули

5.

Программирование на Python | Взаимодействие объектов
Класс пули
Начало точно такое же, как и все остальные, можно просто скопировать
первые строки кода из класса игрока, изменив только картинку:
import pygame
from pygame.math import Vector2
snd_dir = 'media/snd/'
img_dir = 'media/img/'
width = 1366
height = 768
# Путь до папки со звуками
# Путь до папки со спрайтами
# ширина игрового окна
# высота игрового окна
class Bullet(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(img_dir + 'bullet.png')
self.rect = self.image.get_rect()

6.

Программирование на Python | Взаимодействие объектов
Угол поворота
Далее нам необходимо сразу же повернуть пулю в том же направлении, что и игрок. Поэтому во время
создании пули мы будет внутрь неё передавать и игрока. Игрок попадет в метод __init__ Поэтому давайте
создадим переменную, чтобы его там сохранить.
А затем сразу повернем нашу пулю в том же направлении, что и игрок:
class Bullet(pygame.sprite.Sprite):
def __init__(self, player):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(img_dir + 'bullet.png')
self.rect = self.image.get_rect()
self.image = pygame.transform.rotate(self.image, player.angle) # поворот пули

7.

Программирование на Python | Взаимодействие объектов
Необходимые свойства
После поворота, нам сразу необходимо будет перенести пулю в ту же позицию что и игрок:
self.rect.center = Vector2(player.rect.center)
# Пуля там же где и игрок
Затем определить её скорость полета:
self.speed = 30
# Скорость полета пули
И направление её движения в том же направлении, что и игрок:
self.move = self.speed * player.direction
# Направление движения пули от игрока

8.

Программирование на Python | Взаимодействие объектов
Полет пули
Наша пуля должна двигаться постоянно в указанном направлении. Чтобы это было возможно мы должны
создать функцию def update(self) и в ней достаточно будет добавить всего одну команду перемещения:
def update(self):
self.rect.center += self.move
И еще один момент, о котором нужно позаботиться — это уничтожение пули при её вылете за пределы
экрана. Как определить, что пуля оказалась за пределами мы уже знаем. Давайте напишем одну
проверку,
которая объединит сразу все условия. И если проверка будет выполнена, то мы уничтожим пулю
специальной командой:
if self.rect.x > width or self.rect.y > height or self.rect.y < 0 or self.rect.x < 0:
self.kill()

9.

Программирование на Python | Взаимодействие объектов
Финальный вид файла с классом пули:
import pygame
from pygame.math import Vector2
snd_dir = 'media/snd/'
img_dir = 'media/img/'
width = 1366
height = 768
# Путь до папки со звуками
# Путь до папки со спрайтами
# ширина игрового окна
# высота игрового окна
class Bullet(pygame.sprite.Sprite):
def __init__(self, player):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(img_dir + 'bullet.png')
self.image = pygame.transform.rotate(self.image, player.angle)
self.rect = self.image.get_rect()
self.rect.center = Vector2(player.rect.center)
# Пуля там же где и игрок
self.speed = 30
self.move = self.speed * player.direction
# Направление движения пули от игрока
def update(self):
self.rect.center += self.move
if self.rect.x > width or self.rect.y > height or self.rect.y < 0 or self.rect.x < 0:
self.kill()

10.

Учимся стрелять

11.

Программирование на Python | Взаимодействие объектов
Клавиша стрельбы
Теперь, когда наш спрайт полностью настроен, можно его добавить на экран. Для этого сначала настроим
событие, по которому игрок будет стрелять. Переходим в основной файл игры и добавляем в игровой цикл
отслеживание нажатия клавиш:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN:
# Обработка событий
# Проверить закрытие окна
# Проверить нажатие клавиш

12.

Программирование на Python | Взаимодействие объектов
Создаем пулю
Чуть ниже проверяем нажат ли пробел. И если он нажат, то мы просто должны создать спрайт пули и
добавить его ко всем спрайтам, чтобы увидеть на экране:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
bullet = Bullet(player)
all_sprites.add(bullet)
# Обработка событий
# Проверить закрытие окна
# Проверить нажатие клавиш
# Если нажат пробел
# Создаем пулю передавая внутрь игрока
# Добавляем пулю ко всем спрайтам

13.

Групповые
коллизии

14.

Программирование на Python | Взаимодействие объектов
Группы для всех спрайтов
Мы уже с вами создавали группу для абсолютно всех спрайтов и добавляли туда всех подряд. Но теперь
нам нужно еще дополнительно распределить наши спрайты по своим группам, чтобы мы могли отличить
мобов
от игрока и других объектов. Для этого просто переходим в то место, где у нас создавалась наша самая
первая группа и добавим еще группы для мобов, для игроков:
all_sprites = pygame.sprite.Group()
mobs_sprites = pygame.sprite.Group()
bullets_sprites = pygame.sprite.Group()
players_sprites = pygame.sprite.Group()
# Создаем группу для всех спрайтов
# Создаем группу для спрайтов мобов
# Создаем группу для спрайтов пуль
# Создаем группу для спрайтов игроков

15.

Программирование на Python | Взаимодействие объектов
Добавляем спрайты в группы
А теперь, нам нужно не забыть добавить все когда либо создаваемые спрайты в эти
группы. Начнем с игрока и мобов:
all_sprites.add(player)
players_sprites.add(player)
# Добавляем игрока в группу спрайтов
# Добавляем игрока в группу игроков
mobs_sprites.add(enemy_left)
mobs_sprites.add(enemy_right)
mobs_sprites.add(enemy_top)
mobs_sprites.add(enemy_bottom)
# Левых мобов в группу мобов
# Правых мобов в группу мобов
# Верхних мобов в группу мобов
# Нижних мобов в группу мобов

16.

Программирование на Python | Взаимодействие объектов
Добавляем спрайты в группы
И не забудем про пули. Вспомним где они у нас создавались и допишем там еще одну
команду для добавления в нужную группу:
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
bullet = Bullet(player)
all_sprites.add(bullet)
bullets_sprites.add(bullet)
# Создаем пулю передавая внутрь игрока
# Добавляем пулю ко всем спрайтам
# Добавляем пулю ко всем пулям

17.

Программирование на Python | Взаимодействие объектов
Уничтожение спрайтов
Групповые коллизии — это события, которые необходимо постоянно проверять в игровом
цикле. Поэтому перемещаемся внутрь него и пишем следующую команду:
shots = pygame.sprite.groupcollide(bullets_sprites, mobs_sprites, True, True)
shots — это просто переменная, которая хранит в себе информацию о столкновении.
pygame.sprite.groupcollide() — это функция, которая нужна для настройки столкновений
bullets_sprites — первая группа спрайтов за которой следим
mobs_sprites — вторая группа спрайтов за которой следим
True, True — это признаки того нужно ли удалить спрайт после столкновения.
Первый True — означает, что удаляем спрайт их первой группы (в нашем случае — это
пули). Второй True — означает, что удаляем спрайт из второй группы (в нашем случае —
это мобы).

18.

Перерыв
10 мин

19.

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

20.

Программирование на Python | Взаимодействие объектов
Загружаем звуки в класс игрока
Для начала просто загрузим все свойства в класс игрока. У нас будут:
Звук выстрела
Звук взрыва
Звук скрежета
И сразу уменьшим громкость
self.snd_expl = pygame.mixer.Sound(snd_dir + "expl.mp3")
self.snd_expl.set_volume(0.3)
self.snd_shoot = pygame.mixer.Sound(snd_dir + "shoot.mp3")
self.snd_shoot.set_volume(0.3)
self.snd_scratch = pygame.mixer.Sound(snd_dir + "scratch.mp3")
self.snd_scratch.set_volume(0.3)

21.

Программирование на Python | Взаимодействие объектов
Звук выстрела
Теперь просто найдем событие выстрела в игровом цикле и добавим туда звук выстрела:
if event.key == pygame.K_SPACE:
player.snd_shoot.play()
bullet = Bullet(player)
all_sprites.add(bullet)
bullets_sprites.add(bullet)
# Создаем пулю передавая внутрь информацию об игроке
# Добавляем пулю ко всем спрайтам
# Добавляем пулю ко всем пулям

22.

Программирование на Python | Взаимодействие объектов
События столкновения мобов и игроков
Сначала нам нужно запрограммировать столкновения игрока и мобов.
Перейдем в игровой цикл и воспользуемся уже известным нам способом:
scratch = pygame.sprite.groupcollide(mobs_sprites, players_sprites, False, False)
А вот дальше нам нужно немного поработать с полученной переменной scratch. В неё будут записываться
все события коллизий которые произошли между группами мобов и игроков. А значит, мы можем
заглянуть внутрь неё и посмотреть какие именно объекты из этих групп у нас столкнулись, чтобы можно
было выполнить дополнительные действия уже только с этими объектами.

23.

Программирование на Python | Взаимодействие объектов
Функция для возврата спрайта из группы
Нам нужно будет среди группы игроков найти одного нашего, чтобы можно было у него
воспроизвести звук скрежета. Для этого сначала добавим функцию для поиска этого
объекта:
scratch
def
get_hit_sprite(hits_dict):
= pygame.sprite.groupcollide(mobs_sprites, players_sprites, False, False)
for hit in hits_dict.values():
return hit[0]
Это готовая функция, мы её просто добавим до игрового цикла. А дальше можем ею
воспользоваться, чтобы получить тот самый один спрайт и сделать с ним все, что захотим. В
нашем случае пока что только воспроизвести звук скрежета.

24.

Программирование на Python | Взаимодействие объектов
Звук скрежета
Первым делом добавим условие проверки события столкновения. И если это событие
произошло, то получим спрайт из группы игроков с которым столкнулся моб и воспроизведем
его звук:
scratch = pygame.sprite.groupcollide(mobs_sprites, players_sprites, False, False)
if scratch:
sprite = get_hit_sprite(scratch)
# Получаем спрайт из второй группы
sprite.snd_scratch.play()
# Воспроизводим звук скрежета
Важно! Функция get_hit_sprite() получает спрайт только из второй группы, указанной в событии
groupcollide(). Так как мы хотим получать игрока с которым столкнулся моб, то группу игроков мы
ставим на второе место. Также указываем False и False, чтобы спрайты не исчезали при
столкновении.

25.

Программирование на Python | Взаимодействие объектов
Фоновая музыка
Фоновая музыка добавляется до игрового цикла уже известным нам способом
pygame.mixer.music.load(snd_dir + "music.mp3")
pygame.mixer.music.set_volume(0.1)
pygame.mixer.music.play(-1)

26.

Добавляем
звуки взрыва

27.

Программирование на Python | Взаимодействие объектов
Самостоятельная работа
Сейчас вам самостоятельно предстоит добавить звуки взрыва ко всем классам мобов.
И воспроизвести их в момент столкновения пули и мобов (добавить похожий код как для
scratch) только для события shots.
Подсказка есть ниже но попробуйте сделать самостоятельно.

28.

Программирование на Python | Взаимодействие объектов
Подсказка
Сначала идем во все классы мобов и загружаем в них звуки взрыва, делая сразу потише.
self.snd_expl = pygame.mixer.Sound(snd_dir + "expl.mp3")
self.snd_expl.set_volume(0.3)
Затем в игровом цикле добавляем для события shots соответствующую обработку:
shots = pygame.sprite.groupcollide(bullets_sprites, mobs_sprites, False, False)
if shots:
sprite = get_hit_sprite(shots)
# Получаем спрайт из второй группы
sprite.snd_expl.play()
# Воспроизводим звук скрежета
Готово!

29.

Программирование на Python | Взаимодействие объектов
Результат
Весь проект с готовыми файлами можно скачать здесь:
https://github.com/ronmount/gb_shooter/archive/refs/heads/lesson3.zip

30.

Программирование на Python | Взаимодействие объектов
Итоги
Изучили принципы создания спрайтов в определенный момент
Настроили постоянное движение спрайта в указанном
направлении
Узнали что такое групповые коллизии и как их настраивать
Настроили стрельбу игрока
Настроили уничтожение мобов при попадании
Включили звуки в нужных событиях и добавили музыку

31.

Программирование на Python | Взаимодействие объектов
На следующем занятии:
Добавим жизни игроку и мобам
Добавим анимацию взрыва

32.

Немного
повторим

33.

Как можно проверить выход спрайта
за границы экрана в одном условии?

34.

Для чего нужен self.kill() ?

35.

Для чего нужны групповые коллизии?

36.

Как можно включить определенный
звук у конкретного спрайта?

37.

Ваши вопросы

38.

Спасибо
за внимание

39.

Домашнее задание

40.

Заполни, пожалуйста,
форму обратной связи по уроку

41.

Напоминание для преподавателя
● Проверить заполнение Журнала
● Заполнить форму Т22
English     Русский Rules