Практика
Спрайтовая анимация в FM

:: Меню ::
:: На главную ::
:: FAQ ::
:: Заметки ::
:: Практика ::
:: Win API ::
:: Проекты ::
:: Скачать ::
:: Секреты ::
:: Ссылки ::

:: Сервис ::
:: Написать ::

:: MVP ::

:: RSS ::

Яндекс.Метрика


Спрайт представляет собой растровое изображение (как правило небольшого размера), которое может перемещаться по экрану независимо от остального изображения. Спрайты бывают анимированные и не анимированные. Не анимированный спрайт — это простое 2D изображение. Анимированный спрайт представляет собой набор последовательных не анимированных спрайтов (кадров), соединенных в одном графическом файле. К кадрам анимации не предъявляется особых требований за исключением одного — все они должны быть одинакового размера. Для работы с анимированными спрайтами в FM предусмотрен компонент TBitmapListAnimation.

Попробуем создать анимацию на примере компонента TImageControl. Выбираем свойство “Bitmap”, нажимаем кнопку “…” и в выпавшем меню выбираем пункт “Create New TBitmapListAnimation”. Попутно обратим внимание на окно структуры проекта “Structure” – у компонента ImageControl1 появился дочерний компонент BitmapListAnimation1 (запомним, чуть позже мы к этому вернемся).

Пробежимся взглядом по свойствам компонента BitmapListAnimation. AnimationBitmap – именно здесь должен храниться наш анимированный спрайт. Выбираем это свойство, нажимаем кнопку “…”, в выпавшем меню выбираем пункт “Edit…” и загружаем нужный спрайт. Для правильного воспроизведения анимации нужно правильно заполнить еще 2 свойства: “AnimationCount” (количество кадров в нашем спрайте) и “AnimationRowCount” (количество рядов в анимированном спрайте). Свойство “Duration” отвечает за скорость воспроизведения анимации. Обратим внимание на свойство “PropertyName” – его значение равно “Bitmap” и сообщает компоненту BitmapListAnimation о том, какое свойство родительского компонента нужно использовать для отображения анимации.

Осталось установить свойство “Enabled” в True, скомпилировать и запустить проект. Все работает, а мы не написали ни одной строчки кода!

Вернемся к окну структуры проекта и немного поэкспериментируем и иерархией компонентов. Переместим BitmapListAnimation на уровень выше (чтобы он стал дочерним элементом формы). После запуска никакой анимации не будет, что абсолютно логично и ожидаемо – форма не имеет свойства “Bitmap” (попутно обратим внимание, что мы не получили никакой ошибки или исключения). Попробуем указать в свойстве “PropertyName” имя свойства вместе с именем компонента – “ImageControl1.Bitmap”. После запуска анимация снова начинает работать. Из этого автоматически напрашивается вывод – компонент BitmapListAnimation не обязательно должен быть дочерним по отношению к компоненту, который будет использоваться для отображения анимации, главное правильно заполнить поле “PropertyName”. В заключении эксперимента вернем компонент BitmapListAnimation на свое первоначальное место в иерархии, и убедимся в том, что все работает. Для наглядности все возможные рабочие варианты представлены на рисунке ниже.


Во время воспроизведения анимации потаскаем форму мышкой по экрану и увидим, что анимация не замирает и даже не притормаживает. Все потому, что компонент дружит с потоками и работает с анимацией вне UI потока приложения.

Если Вас, по каким-то причинам, не устраивает TImageControl (например, своим непрозрачным фоном), то можно использовать компонент TImage. Правда сделать это придётся немного по-другому. Связано это с тем, что свойство Bitmap у компонента TImage не опубликовано. Действуем по описанному выше методу:
  • Кидаем на форму компоненты TImage и TBitmapListAnimation;
  • Делаем TBitmapListAnimation дочерним по отношению к TImage;
  • Настраиваем компонент TBitmapListAnimation так, как описано выше, а в свойстве “PropertyName” пропишем “Bitmap”.
Запускаем и видим что все прекрасно работает.

На ход воспроизведения анимации можно влиять изменением значения свойства Interpolation, но не всего можно добиться с его помощью. Понадобилось мне сделать паузу между циклами воспроизведения (то есть после отображения последнего кадра анимации перед отображением первого). Сделать это настройкой свойств компонента у меня не получилось написать несколько строчек кода.

Хотя, можно было обойтись и без программирования. Можно продублировать последний кадр анимации столько раз, но сколько длинной должна быть пауза но по понятным соображениям этот вариант был сразу отброшен. Во-первых, это приводит к увеличению размера спрайта (что, в конечном счете, отразится на размере программы). Во-вторых, при необходимости изменить длительность паузы придется редактировать спрайт, что крайне неудобно. И, наконец, в-третьих, мы не сможем изменять длительность паузы в runtime. Так что немного покодим:

procedure TMainForm.BitmapListAnimationFinish(Sender: TObject);
begin
   if RB_Fighter.IsChecked then
   begin
      BitmapListAnimation.Enabled := False;
      Timer.Enabled := True;
   end;
end;

procedure TMainForm.TimerTimer(Sender: TObject);
begin
   if RB_Fighter.IsChecked then
   begin
      Timer.Enabled := False;
      BitmapListAnimation.Enabled := True;
   end;
end;

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

В качестве украшения можно добавить к TImage эффект ReflectionEffect, получается очень красиво. На этом все, успехов в программировании!

.: Пример к данной статье (XE6):.


При использовании материала - ссылка на сайт обязательна