Анимация объектов: keyframe, tweening

Что такое анимация в играх?

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

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


Ключевые кадры (Keyframe) 🎯

Ключевой кадр — это моментальный снимок состояния объекта в определенный момент времени. Вместо того чтобы вручную задавать положение объекта для каждого кадра анимации (это очень долго!), ты задаешь только самые важные, «ключевые» позиции.

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

  • Стартовая позиция (на земле)
  • Пик прыжка (в воздухе)
  • Конечная позиция (снова на земле)

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

💡 Совет: Думай о ключевых кадрах как об опорных точках маршрута. Ты отмечаешь на карте города, через которые нужно проехать, а движок прокладывает между ними дорогу.

Сглаживание (Tweening) ➕

Tweening (сокращение от «in-betweening» — «промежуточный») — это процесс, при котором движок автоматически генерирует плавные переходы между заданными ключевыми кадрами.

Ты говоришь программе: «Вот объект в точке A в момент времени t=0. А вот он же в точке B в момент времени t=2». Алгоритмы сглаживания вычисляют, где должен находиться объект в любой промежуточный момент времени, например, при t=1.

Самый простой и распространенный тип сглаживания — линейная интерполяция, или Lerp.

Линейная интерполяция (Lerp)

Это математическая формула, которая плавно переходит от начального значения к конечному. Вот как она выглядит для перемещения объекта из точки A в точку B:

новая_позиция = A + (B - A) * t

Где t — это фактор времени, обычно значение от 0.0 (начало анимации) до 1.0 (конец анимации).

Давай разберем на простом примере. Пусть наш мячик начинает прыжок в позиции Y = 0 и достигает пика в Y = 5.

  • При t = 0: 0 + (5 - 0) * 0 = 0 (мы в начале)
  • При t = 0.5: 0 + (5 - 0) * 0.5 = 2.5 (мы на полпути!)
  • При t = 1: 0 + (5 - 0) * 1 = 5 (мы достигли цели!)

📘 Заметка: Интерполировать можно не только позицию! Этой же формуле можно подвергнуть вращение, размер, цвет прозрачность — любые числовые значения.

Типы Tweening: Easing Functions

Линейное движение (Lerp) часто выглядит неестественно и роботизировано. В реальном мире объекты ускоряются и замедляются. Для этого используются функции плавности (Easing Functions). Они изменяют значение t перед его подстановкой в формулу Lerp, чтобы придать движению характер.

Вот основные типы:

Тип Как выглядит Где использовать
Ease-In (Ускорение) Начинается медленно, заканчивается быстро Объект, который падает под действием гравитации
Ease-Out (Замедление) Начинается быстро, заканчивается медленно Торможение машины, приземление мяча
Ease-In-Out Сочетает в себе ускорение и замедление Наиболее естественное движение. Универсальный выбор.


Практика: Задача на закрепление

Давай применим теорию на практике. Решим небольшую, но очень важную задачу.

Условие задачи

Ты создаешь игру, и тебе нужно, чтобы монетка плавно возникала на экране, увеличиваясь в размере от 0 до 1. Анимация должна длиться 1 секунду и использовать эффект замедления (Ease-Out). Напиши функцию, которая вычисляет масштаб монетки в любой момент времени t (от 0 до 1 секунды).

Пошаговое решение

Шаг 1: Определяем ключевые кадры

Нам нужно всего два ключевых кадра:

  • Начальный кадр (t=0): Масштаб = 0
  • Конечный кадр (t=1): Масштаб = 1

Шаг 2: Выбираем функцию плавности

По условию нам нужен Ease-Out (замедление). Одна из простейших функций для этого — квадратичная: t' = 1 - (1 - t) * (1 - t) или t' = 1 - (1 - t)^2. Она преобразует наше линейное время t в нелинейное t'.

Шаг 3: Пишем функцию интерполяции

Теперь совмещаем линейную интерполяцию с функцией плавности.

function getCoinScale(t) {
    // t - это время от 0 до 1
    // Применяем функцию Ease-Out (квадратичную)
    let easedT = 1 - Math.pow(1 - t, 2);

    // Выполняем линейную интерполяцию (Lerp) между 0 и 1, используя преобразованное время
    let scale = 0 + (1 - 0) * easedT;

    return scale;
}
Скрыть рекламу навсегда

📘 VK Видео — обучение без ограничений

Все уроки доступны без VPN, без блокировок и зависаний.

Можно смотреть с телефона, планшета или компьютера — в любое время.

▶️ Смотреть на VK Видео