§ 17. Анимация

17.6. Спрайтовая анимация

Используя битовые образы, можно создавать спрайтовую анимацию.

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

Спрайты являются одним из самых популярных способов создания больших и сложных сцен, так как позволяют манипулировать и управлять каждым изображением в отдельности.

Спрайты использовались при создании анимации в примерах 17.13 (луна) и 17.14 (бабочка). В этих примерах спрайт содержал фиксированное изображение. Современным подходом к применению спрайтов в анимации является использование раскадровок (spritesheet — атлас спрайтов) — графических файлов, содержащих несколько фаз движения какого-либо объекта (пример 17.15). Быстрая смена отдельных кадров позволяет создать иллюзию движения. Такую анимацию называют спрайтовой.

Удобно использовать раскадровки, в которых все кадры имеют одинаковую ширину (высоту).

Алгоритм создания анимации с использованием атласа спрайтов будет аналогичен алгоритму, рассмотренному в примере 17.5:

  1. Сохранить часть фона.
  2. Нарисовать первый кадр спрайта.
  3. Запустить таймер.
  4. Пока таймер работает:
    4.1. восстановить фон;
    4.2. рассчитать новое положение объекта;
    4.3. сохранить часть фона;
    4.4. перейти к следующему кадру;
    4.5. нарисовать кадр.

Пример 17.16. Создать проект, в котором бабочка будет летать вокруг цветка. Для полета бабочки использовать спрайт с раскадровкой.

Этапы выполнения задания

  1. Анимация запускается сразу при загрузке формы (без кнопки запуск).
  2. Если не учитывать необходимость смены кадров из атласа спрайтов, то задание аналогично примеру 17.13. Рассмотрим смену кадров.
  3. При каждом срабатывании таймера будем выделять новый кадр из раскадровки. Если горизонтальная координата текущего кадра стала больше, чем ширина атласа спрайтов, то выделение начинается сначала.
  4. Атлас спрайтов для бабочки состоит из 18 кадров, поэтому при каждом срабатывании таймера значение переменной t будем изменять на   .

Слово «спрайт» было придумано в 1970-е годы сотрудником компании Texas Instruments: их новая микросхема TMS9918 могла аппаратно отображать небольшие движущиеся картинки поверх неподвижного фона.

Пример 17.15. Примеры раскадровок[1]:


[1] Изображения бесплатных раскадовок взяты с сайта https://ru.freepik.com/

Пример 17.16. Раскадровка бабочки (первые четыре кадра):

Описание переменных:

Graphics::TBitmap

  *kadr = new Graphics::TBitmap(),

  *spritesheet = new Graphics::TBitmap(),

  *fon = new Graphics::TBitmap(),

  *fon_kadr = new Graphics::TBitmap();

int w, h, x_fly, y_fly, x_k, y_k;

int x_c = 150, y_c =120, R = 120;

//количество кадров

int k = 18;

bool f = false;

TRect pr_kadr, pr_fon, pr_fly;

double t = 0, pi;

Обработчик события FormCreate для формы.

void __fastcall TForm1::

FormCreate(TObject *Sender)

{

  //загрузка изображений

  fon -> LoadFromFile("podsolnuh.bmp");

  Image1 -> Picture -> Assign(fon);

  spritesheet -> LoadFromFile("fly.bmp");

  w = spritesheet -> Width / 18;

  h = spritesheet -> Height;

  //определение битового образа

  //для хранения кадра бабочки

  kadr -> Width = w;

  kadr -> Height = h;

  kadr -> Transparent = true;

  pr_kadr = Bounds(0, 0, w, h);

  pr_fly  = pr_kadr;

  //начальный кадр

  x_k = 0;

  y_k = 0;

  kadr -> Canvas -> CopyRect(pr_kadr,

      spritesheet -> Canvas, pr_fly);

  //определение битового образа

  //для хранения части фона

  fon_kadr -> Width = w;

  fon_kadr -> Height = h;

  //начальное положение бабочки

  x_fly = x_c;

  y_fly = y_c - R;

  //сохранение части фона под бабочкой

  pr_fon = Bounds(x_fly, y_fly, w, h);

  fon_kadr -> Canvas -> CopyRect

    (pr_kadr, fon -> Canvas, pr_fon);

  //рисование бабочки

  Image1 -> Canvas -> Draw

     (x_fly, y_fly, kadr);

  pi = acos(-1.);

}

Обработчик события OnTimer для таймера:

void __fastcall TForm1::
Timer1Timer(TObject *Sender)

{

  //восстановление фона

  Image1 -> Canvas -> Draw

      (x_fly, y_fly, fon_kadr);

  //новый кадр бабочки

  x_k += w;

  if (x_k > w * k)

    x_k = 0;

  pr_fly = Bounds(x_k, y_k, w, h);

  kadr -> Canvas -> CopyRect (pr_kadr,

     spritesheet -> Canvas, pr_fly);

  //новое положение бабочки

  += 0.349;

  if (> 2 * pi)

    t = 0;

  x_fly = x_c + ceil(* sin(t));

  y_fly = y_c - ceil(* cos(t));

  //сохранение части фона

  pr_fon = Bounds(x_fly, y_fly, w, h);

  fon_kadr -> Canvas -> CopyRect

    (pr_kadr, fon -> Canvas, pr_fon);

  //рисование бабочки

  Image1 -> Canvas -> Draw

       (x_fly, y_fly, kadr);

}