§ 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);

}