16.53M
Категория: ПрограммированиеПрограммирование

Программирование на Python. Урок 10. Анимация и передвижение

1.

Программирование
на Python
Урок 10
Анимация и передвижение

2.

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

3.

Программирование на Python | Анимация и передвижение
Что будет на уроке сегодня?
Узнаем что такое вектор и зачем он нужен
Научимся вращать игрока и перемещать
в направлении взгляда
Настроим логику респауна мобов
Научимся перемещать и вращать мобов
в случайном направлении

4.

Что такое вектор
и зачем он нужен

5.

Программирование на Python | Анимация и передвижение
Что такое вектор
Вектор — это просто отрезок с направлением. Нарисуйте на листе бумаге стрелку — это и есть вектор!
Вы ясно видите где у него начало и где конец. Также понимаете куда он показывает. Если вы покрутите
листок бумаги, то будет меняться направление стрелки (вектора).
Теперь понимаете зачем нужен вектор в играх? :) Верно! Одно из его назначений — это вращение объектов
и определение их направления. Этим мы и займемся на этом уроке!

6.

Программирование на Python | Анимация и передвижение
Подключаем вектор к классам
Перейдем в класс игрока и подключим модуль с вектором:
import pygame
from pygame.math import Vector2
Перейдем в класс игрока и подключим модуль с вектором:
Цифра 2 говорит о том, что мы будем работать в 2-мерном пространстве. Данный модуль
необходимо подключить ко всем классам, которые будут вращаться (это и игрок и все
мобы).

7.

Подготовка
для вращения

8.

Программирование на Python | Анимация и передвижение
Подключаем необходимые свойства
Одного вектора недостаточно. Чтобы осуществить вращение, мы должны добавить
нашим спрайтам еще несколько важных свойств. Сначала создадим копию нашей
картинки:
self.copy = self.image
# Копия картинки
Так устроен pygame — мы будем вращать копию вместо основной картинки. А когда копию повернем,
запишем её на место основной картинки. Это нужно, чтобы основная картинка не смазывалась
при вращении и одновременной отрисовке на экране.

9.

Программирование на Python | Анимация и передвижение
Подключаем необходимые свойства
Теперь нам важно создать вектор в том положении и в том направлении, в котором
находится наш игрок. Сначала зададим положение:
self.position = Vector2(self.rect.center)
# Стартовая позиция вектора
Здесь мы создаем наш вектор и указываем центр рамки спрайта. В таком виде всё будет корректно
располагаться и наш вектор как бы приклеивается ровно к центру рамки и будет одним целым с ней.

10.

Программирование на Python | Анимация и передвижение
Подключаем необходимые свойства
Далее указываем направление. Так как картинка нашего спрайта смотрит ровно вверх, то и
вектор наш тоже должен смотреть ровно вверх. Чтобы это сделать напишем ниже следующую
команду:
self.direction = Vector2(0, -1)
# Направление вектора - “вверх”
В итоге у нас получится примерно вот такая ситуация:
Конечно же рамки спрайта и самого вектора не будет видно в
игре. Но мы будем знать, что именно так они будут настроены.

11.

Программирование на Python | Анимация и передвижение
Подключаем необходимые свойства
Ещё один параметр,, который нам необходимо добавить — это угол поворота. В начале он равен
0, так как наш спрайт в начале игры получается никуда не повернут:
self.angle = 0
# Угол поворота

12.

Программирование на Python | Анимация и передвижение
Подключаем необходимые свойства
И последний параметр, который нам необходимо добавить — это скорость движения.
Мы делаем скорость 5, но если вам покажется, что этого мало – можете поддать газу!
self.speed = 5
# Скорость движения
На этом со свойствами закончили.
copy, position, direction и angle необходимо добавить всем классам врагов. Скорость добавлять не
нужно, у них будут свои свойства для

13.

Функция
для вращения

14.

Программирование на Python | Анимация и передвижение
Создаем функцию вращения
Вращение — это не самая простая процедура в играх. Для неё нужна отдельная функция. Давайте
создадим
её для нашего класса игрока. Это будет та же конструкция, что и __init__ или update. Но внутри будет код,
который будет вращать наш спрайт:
Соблюдая отступы на том же уровне что def других функция создадим новую:
def rotate(self, rotate_speed):
Обратите внимание, что внутри rotate мы сначала указываем self (это требование ООП). А после можем
указывать параметры, которые наша функция будет принимать. А принимать она будет один параметр,
задающий скорость вращения спрайта. Мы будем указывать скорость при вызове данной функции.

15.

Программирование на Python | Анимация и передвижение
Направление взгляда
Внутри функции rotate начнем писать команды. Вначале изменим направление
взгляда (вращаем ту самую стрелку вектора)
def rotate(self, rotate_speed):
self.direction.rotate_ip(-rotate_speed)
# Изменяем направление взгляда

16.

Программирование на Python | Анимация и передвижение
Изменяем угол поворота
Дальше мы узнаем на какой угол повернулась стрелка и сохраним
этот угол поворота в соответствующей переменной self.angle
def rotate(self, rotate_speed):
self.direction.rotate_ip(-rotate_speed)
self.angle += rotate_speed
# Изменяем направление взгляда
# Изменяем угол поворота

17.

Программирование на Python | Анимация и передвижение
Поворот копии
Теперь, когда знаем угол, мы можем повернуть наш спрайт. Но поворачиваем не сам спрайт, а копию
картинки спрайта. И полученную развернутую копию уже записываем внутрь основной картинки:
def rotate(self, rotate_speed):
self.direction.rotate_ip(-rotate_speed)
# Изменяем направление взгляда
self.angle += rotate_speed
# Изменяем угол поворота
self.image = pygame.transform.rotate(self.copy, self.angle) # Поворот картинки

18.

Программирование на Python | Анимация и передвижение
Получаем новую рамку и заканчиваем
После поворота картинки рамка станет немного другой. Мы должны это учитывать, чтобы правильно
рассчитывать коллизии. Поэтому последней командой мы должны получить новую рамку:
def rotate(self, rotate_speed):
self.direction.rotate_ip(-rotate_speed)
# Изменяем направление взгляда
self.angle += rotate_speed
# Изменяем угол поворота
self.image = pygame.transform.rotate(self.copy, self.angle) # Поворот картинки
self.rect = self.image.get_rect(center=self.rect.center)
# Изменение рамки

19.

Включаем
вращение

20.

Программирование на Python | Анимация и передвижение
Функция update()
Все действия для любых спрайтов должны быть написаны внутри специальной функции update. Эта
функция будет вызываться в игровом цикле. И весь код написанный внутри будет работать постоянно,
пока работает игровой цикл. Давайте создадим эту функцию:
def update(self):
# Функция для описания действия спрайта
И внутри сразу напишем код, с помощью которого pygame сможет следить за нажатием клавиш:
key = pygame.key.get_pressed()
# Сохраняем нажатие на кнопку (любую)

21.

Программирование на Python | Анимация и передвижение
Вращение игрока
Теперь мы можем по нажатию клавиш стрелки вправо и влево вращать наш спрайт. Для этого нам просто
необходимо вызвать данную функцию при соответствующем событии:
def update(self):
key = pygame.key.get_pressed()
if key[pygame.K_RIGHT]:
self.rotate(-5)
if key[pygame.K_LEFT]:
self.rotate(5)
# Функция для описания действия спрайта
# Сохраняем нажатие на кнопку (любую)
# Если нажата кнопка стрелка вправо
# Вращаемся на 5 по часовой стрелке
# Если нажата кнопка стрелка влево
# Вращаемся на 5 против часовой стрелки
Как мы помним, функция принимает один параметр — скорость вращения. Так вот с помощью числа мы
задаем скорость вращения. А знак «минус» может менять направление вращения. Отрегулируйте для себя
удобную скорость вращения.

22.

Программирование на Python | Анимация и передвижение
Вращение мобов
У мобов все проще. Они должны вращаться постоянно, поэтому просто внутри update будем вызывать
функцию вращения. Можете сделать разные скорости и разные направления вращения разным мобам:
def update(self):
self.rotate(5)
# Вращаемся на 5 градусов против часовой стрелки

23.

Перерыв
10 мин

24.

Настраиваем
движение

25.

Программирование на Python | Анимация и передвижение
Корректируем движение игрока
Наш игрок начал вращаться, но по стрелкам вверх и вниз он двигается не в направлении
взгляда, а просто вверх и вниз. Нужно это исправить. Чтобы двигаться в направлении
движения, необходимо производить две операции:
1.
2.
Изменить позицию вектора
Переместить рамку спрайта на эту позицию
if key[pygame.K_UP]:
self.position += self.speed * self.direction
self.rect.center = self.position
if key[pygame.K_DOWN]:
self.position -= self.speed * self.direction
self.rect.center = self.position
# Если нажата кнопка стрелка вперед
# Изменяем позицию вперед
# Переносим рамку на новую позицию
# Если нажата кнопка стрелка вниз
# Изменяем позицию назад
# Переносим рамку на новую позицию

26.

Программирование на Python | Анимация и передвижение
Добавляем движение мобам
Для начала давайте возьмем один из классов мобов EnemyLeft и добавим движения ему.
Создадим свойства характеризующие его скорость. Здесь уже пригодятся два значения
— скорость по вертикали и по горизонтали:
self.speedx = random.randint(1, 5)
self.speedy = random.randint(-5, 5)
Для большего разнообразия мы делаем скорости случайными. Причем интервал
разный. Так как левые мобы двигаются только вправо, то для скорости по
горизонтали — это интервал только из положительных чисел (от 1 до 5). А вот по
вертикали они могут двигаться как вверх так и вниз, поэтому интервал содержит в
себе числа от -5 до 5.

27.

Программирование на Python | Анимация и передвижение
Добавляем движение мобам
Далее нам необходимо добавить в функцию update, изменение положение спрайтов:
def update(self):
self.rotate(5)
self.rect.x += self.speedx
self.rect.y += self.speedy
Теперь спрайт, находящийся слева начал двигаться!

28.

Программирование на Python | Анимация и передвижение
Респаун мобов
Возникла другая проблема — как только спрайт скроется за краем экрана, он продолжит свое движение
за его пределами и мы его больше никогда не увидим. Поэтому, давайте напишем проверку пересечения
нашим спрайтом границ экрана. Делается это с помощью конструкций if.
Нам нужно понять какие именно границы может пересекать наш спрайт. Раз он появляется слева,
то пересекать он может все границы кроме левой. Пишем условие проверки:
if self.rect.x > width or self.rect.y > height or self.rect.bottom < 0:

29.

Программирование на Python | Анимация и передвижение
Респаун мобов
А внутри данного условия напишем логику для респауна. По сути у нас есть уже все команды, нам их
просто надо скопировать. А именно: мы должны перенести наш спрайт снова в случайную позицию слева.
И дать ему случайные значения скоростей. По сути у нас все команды эти есть. Нужно просто перенести
их из конструктора внутрь нашей проверки:
if self.rect.x > width or self.rect.y > height or self.rect.bottom < 0:
self.rect.x = 0
self.rect.y = random.randint(0, height)
self.speedx = random.randint(1, 5)
self.speedy = random.randint(-5, 5)

30.

Настраиваем
движение
остальным мобам

31.

Программирование на Python | Анимация и передвижение
Самостоятельная работа
Теперь вам предстоит самостоятельно настроить перемещение и респаун остальным
мобам. Чтобы вам было проще, вот всё что вам может пригодиться:
self.rect.x > width
— условие проверки на пересечение правой границы
self.rect.right < 0
— условие проверки на пересечение левой границы
self.rect.y > height
— условие проверки на пересечение нижней границы
self.rect.bottom < 0 — условие проверки на пересечение верхней границы
self.speedx = random.randint(1, 5)
5
self.speedx = random.randint(-5, -1)
self.speedx = random.randint(-5, 5)
self.speedy = random.randint(1, 5)
self.speedy = random.randint(-5, -1)
self.speedy = random.randint(-5, 5)
— движение вправо со случ. скоростью от 1 до
— движение влево со случ. скоростью от 1 до 5
— движение влево и вправо со случ. скоростью
— движение вниз со случ. скоростью от 1 до 5
— движение вверх со случ. скоростью от 1 до 5
— движение вверх и вниз со случ. скоростью

32.

Программирование на Python | Анимация и передвижение
Класс EnemyLeft
def update(self):
self.rotate(5)
self.rect.x += self.speedx
self.rect.y += self.speedy
# Респаун при выходе за правую, верхнюю, нижнюю границы
if self.rect.x > width or self.rect.y > height or self.rect.bottom < 0:
self.rect.x = width
self.rect.y = random.randint(0, height)
self.speedx = random.randint(1, 5)
self.speedy = random.randint(-5, 5)

33.

Программирование на Python | Анимация и передвижение
Класс EnemyRight
def update(self):
self.rotate(5)
self.rect.x += self.speedx
self.rect.y += self.speedy
# Респаун при выходе за левую, верхнюю, нижнюю границы
if self.rect.x < 0 or self.rect.y > height or self.rect.bottom < 0:
self.rect.x = width
self.rect.y = random.randint(0, height)
self.speedx = random.randint(-5, -1)
self.speedy = random.randint(-5, 5)

34.

Программирование на Python | Анимация и передвижение
Класс EnemyBottom
def update(self):
self.rotate(5)
self.rect.x += self.speedx
self.rect.y += self.speedy
# Респаун при выходе за левую, правую и верхнюю границы
if self.rect.x > width or self.rect.right < 0 or self.rect.bottom < 0:
self.rect.x = random.randint(0, width)
self.rect.y = height
self.speedx = random.randint(-5, 5)
self.speedy = random.randint(-5, -1)

35.

Программирование на Python | Анимация и передвижение
Класс EnemyTop
def update(self):
self.rotate(5)
self.rect.x += self.speedx
self.rect.y += self.speedy
# Респаун при выходе за левую, правую и нижнюю границы
if self.rect.x > width or self.rect.right < 0 or self.rect.top > height:
self.rect.x = random.randint(0, width)
self.rect.bottom = 0
self.speedx = random.randint(-5, 5) # Мобы двигаются влево и вправо
self.speedy = random.randint(1, 5)
# Мобы двигаются вниз по оси Y

36.

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

37.

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

38.

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

39.

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

40.

Что такое вектор?

41.

Какой интервал нужно задать,
чтобы объект летел либо вверх либо вниз?

42.

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

43.

Почему мы вызываем функцию rotate()
у мобов внутри update, а у игрока только
при нажатии кнопок?

44.

Ваши вопросы

45.

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

46.

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

47.

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

48.

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