Движенье — жизнь. Анимации в новелле
Доброго времени суток, уважаемые читатели паблика «Алый вестник». С вами Тотал (Сергей), и в сегодняшнем выпуске нашей постоянной рубрики «Среда разработки» мы займёмся анимациями в новеллах.
Быть или не быть? Вот в чем вопрос.
Что касается анимаций в новеллах, есть три принципиально разных мнения.
Часть людей считают, что любое шевеление на экране отвлекает от чтения текста, а значит анимации не нужны.
Другие уверены, что визуальные новеллы уже давно «выросли» из формата «Статичные картинки с текстом», и на экране должно двигаться буквально всё, начиная с элементов фонов типа занавесок, вентиляторов, огня в камине и заканчивая полной анимацией персонажей, их волос, глаз, губ, конечностей и одежды.
И есть третья категория (к ней отношусь и я), люди из которой придерживаются правила золотой середины. Анимация должна добавлять атмосферы в игру, а не создавать её. Поэтому имеет смысл добавлять движение по остаточному принципу, когда готово всё остальное.
Поскольку данный цикл посвящён разработке на движке Ren'Py, то и приёмы работы с анимациями будут описаны для этого скриптового языка, даже почти без применения голого python'а.
Сразу хочется отметить, что Ren'Py не умеет работать с анимациями в привычном нам смысле. Нельзя просто так взять и закинуть анимированный gif в новеллу.
Есть два варианта «анимации»: покадровая смена изображений и перемещение по экрану с поворотами и прочим.
На самом деле ещё можно сделать видеовставку, но это уже читы. И ещё у одного знакомого почти вышло подружить RenPy и Live2D, но выглядело это достаточно стрёмно.
Основа основ, или сначала был кадр.
Давайте вспомним, как объявляются изображения в Ren'Py (да, я помню, что новые версии уже не требуют ручного объявления, но в данном случае это нужно для подготовки):
image kvadratik = 'images/test/kvadrat.png'
То же самое можно записать иначе:
image kvadratik:
....'images/test/kvadrat.png'
(Точки всё так же обозначают пробелы-отступы в коде, поскольку ВК портит оформление).
Теперь добавим ещё один кадр и заставим квадрат превращаться в прямоугольник и обратно (это создаст эффект движения):
image kvadratik:
....'images/test/kvadrat.png'
....pause 0.5
....'images/test/nekvadrat.png'
....pause 0.5
....repeat
Что мы здесь видим? По сути, простейший пример использования ATL (языка анимации и трансформации, встроенного в RenPy), взятый из документации.
Объявили изображение, состоящее из двух кадров анимации, сменяющих друг друга с периодом в полсекунды. Repeat нужен для зацикливания анимации.
Примерно таким образом, добавляя кадры и меняя время их появления, уже можно получить простенькую анимацию.
Например, моргание. Помните, для реалистичности нужно не менее трех кадров: глаза закрыты, открыты и промежуточные состояния.
Хотя для большого числа кадров удобнее использовать метод, который я подсмотрел у 7DOTS. Там ещё и эффект перехода между кадрами есть…
Двигаемся дальше
Покадровая анимация — это, конечно, хорошо, но что делать, если нужно перемещение или другие эффекты? Вот тут-то и используем ATL на всю мощность.
Движение отдельных частей картинки, изменение прозрачности, (не)линейное перемещение объектов на экране — это далеко не полный список возможностей.
Основные операторы (функции, команды), которые я применяю при проектировании анимаций — это управление прозрачностью (alpha для создания разных эффектов от освещения), линейное и нелинейное изменение координат (linear, easein, easeout, xpos, ypos) и поворот вокруг заданной точки на заданный угол (rotate).
Кстати, никто не запрещает использовать более сложные визуальные эффекты, подобрать которые можно с помощью шпаргалки с функциями плавности и соответствия этим функциям из документации RenPy.
В самом простом случае, линейное перемещение из точки (x1, y1) в (x2, y2) будет выглядеть так:
show kvadrat:
....xpos 100 ypos 100
....linear 5.0 xpos 200 ypos 1000
Что мы делаем: показали квадрат в позиции (100, 100), потом за 5 секунд по прямой перетащили его в новое положение.
Поворот:
show kvadrat:
....xalign .5 yalign .5 rotate 0
....linear 5.0 yalign .5 clockwise circles 1 rotate 360
Поместили квадрат в центр экрана и повернули 1 раз вокруг центра. clockwise — значит по часовой стрелке, circles 1 — значит без сужения или расширения по спирали.
А если надо не вокруг центра? Просто добавим alignaround (0.3, 0.3):
show kvadrat:
....xalign .5 yalign .5 rotate 0
....alignaround (0.3, 0.3)
....linear 5.0 yalign .5 counterclockwise circles 1 rotate 360
Кто нашел ещё отличие от предыдущего примера?
Свет:
Для динамичного освещения (допустим, при наличии на сцене источника огня) можно поверх статичного BG добавить слой света и менять его прозрачность.
image k_n_fr:
....parallel:
........"images/bg/K-NIGHT/DINNER_HOLL_night.png"
....parallel:
........"images/bg/K-NIGHT/DINNER_HOLL_night_FIRE_layer.png"
........alpha 0.0
........linear 1.0 alpha 0.99
.......linear 1.5 alpha 0.0
....repeat
Что здесь? При объявлении фона используем два блока, выполняются они одновременно параллельно. Первый просто выведет статичную картинку, второй же управляет прозрачностью слоя света, меняя его видимость.
К сожалению, гифка с записью экрана или видео не передаст в полной мере результат, поэтому (минутка рекламы) смотрим, что получилось в игре «Сопредельные острова»— сцены в трактире, трюме, и в «Плакучей иве» (в которой моя роль — кодер-наёмник для вещей сложнее «внести текст») — сцены в ночном каминном зале.
Эмоции:
Если требуется анимация лица (или других частей тела), удобнее всего собирать спрайт через LiveComposite. К базовому образу добавляются различные элементы с нужными координатами и условиями.


Пример снова взят из «Плакучей ивы» — несложная анимация моргания у котейки и слегка двигающиеся уши у другого. Чтобы было более реалистично, добавим элемент случайности. С некоторой вероятностью котик моргнёт дважды. Объявим отдельно глаза и добавим их на базовый спрайт. А для большого кота добавим ещё строку subpixel True для того, чтоб скрыть рывки при анимации.
Примерно таким же образом можно сделать практически любую анимацию. Где-то подойдёт покадровая сборка, где-то перемещение и другие приемы ATL.
Естественно, я не претендую на истину в последней инстанции. Всегда можно сделать иначе, и это тоже будет работать.
И напоследок лайфхак.
Что делать, если у вас есть только анимированный гиф из 100500 кадров? Как быстро разобрать на кадры?
Закидываем гифку в фотошоп, и вуаля — он сам создаёт раскадровку. Остаётся сохранить нужные кадры-слои или все сразу пакетно. Для этого щелкаем правой кнопкой мышки на слой в списке — быстрый экспорт в PNG. Если предварительно выделить несколько слоев или все (через Shift или Ctrl) — они будут сохранены в указанную папку со своими именами.
Таковы, вкратце, возможности ATL (далеко не все), которые можно использовать для придания новелле динамики.
Автор статьи и оформление: Total
Обложка: miku_xikka
В статье использованы материалы 7DOTS и TechnoCat Games.
