Russian Belarusian English German Japanese Ukrainian

Создание простой мультипликации

CuBook4.55

Каждый, наверно, примерно представляет себе принципы создания мультипликационных фильмов, знает, что они представляют собой совокупность множества кадров, каждый из которых чуть-чуть отличается от предыдущего. Это при быстром поочередном просмотре кадров создает иллюзию движения. Вам, конечно, в своей работе не придется рисовать с помощью C++Builder мультфильмы. Для этого имеются совершенно другие инструменты. Но некоторые простенькие анимации - оживление изображений, иногда желательно делать. Например, при создании какой-нибудь обучающей программы может захотеться оживить какие-то схемы или условные изображения механизмов, чтобы показать в движении взаимодействие их отдельных составляющих. Или применить анимации типа тех, которые используются в программе Windows «Проводник» при копировании и удалении файлов. Чтобы не связываться с изображениями каких-то механизмов, сделаем нечто всем понятное: например условное изображение человечка, шагающего и бьющего при этом в литавры.
 
Откройте новое приложение, перенесите на форму компоненты Image, кнопку Button и таймер Timer. Кнопку разместите внизу формы. Основную площадь формы должен занимать компонент Image, на котором и будет рисоваться изображение.
 
Таймер будет задавать темп смены кадров. Поскольку в приложении у нас будет всего два кадра, задайте значение свойства Interval таймера достаточно большим, например, 500 (поскольку интервалы задаются в миллисекундах, то это значение соответствует 0,5 сек). Значение параметра Enabled таймера установите в false. Таймер у нас будет управляться кнопкой.
 
Теперь размещение компонентов закончено. Надо ввести текст программы. В заголовочном файле добавьте строку:
void __fastcall Draw();
Это объявление функции, которая будет рисовать изображение. А текст самого модуля может иметь вид: 
short int num = 0;
short int H=20; // шаг
short int Xpos = 2 * H; // координата туловища
short int Ypos = 120; // наша Земля
short int Hmen = 30; // высота тела
short int Rhead = 10; // радиус головы
short int Rhead2 = Rhead/2; // радиус литавров
short int revers = 1; // направление движения
short int L = H * 1.41; // длина ноги
Для формы функции Draw() пишем следующее:
void __fastcall TForml::Draw()
{
short int Yhead;
switch (num)
  {
  case 0:
  Yhead = Ypos-H-Hmen;
  Image1->Canvas->MoveTo(Xpos-H,Ypos);
  Image1->Canvas->LineTo(Xpos,Ypos-H);
  Image1->Canvas->LineTo(Xpos+H,Ypos);
  Image1->Canvas->MoveTo(Xpos,Ypos-H);
  Image1->Canvas->LineTo(Xpos,Yhead);
  Image1->Canvas->MoveTo(Xpos+revers*H,Yhead-H);
  Image1->Canvas->LineTo(Xpos,Yhead+4);
  Image1->Canvas->Ellipse(Xpos+revers*H-Rhead2,Yhead-H-Rhead2,Xpos+revers*H +Rhead2,Yhead-H+Rhead2);
  Image1->Canvas->LineTo(Xpos+revers*H,Yhead+H);
  Image1->Canvas->Ellipse(Xpos+revers*H-Rhead2,Yhead+H-Rhead2,Xpos+revers*H+Rhead2,Yhead+H+Rhead2);
  Image1->Canvas->Ellipse(Xpos-Rhead,Yhead, Xpos+Rhead,Yhead-2*Rhead);
  Image1->Canvas->Rectangle(Xpos-Rhead,Yhead-2*Rhead-1,Xpos+Rhead,Yhead-2*Rhead-4);
  break;
  case 1:
  Yhead = Ypos-L-Hmen;
  Image1->Canvas->MoveTo(Xpos,Ypos);
  Image1->Canvas->LineTo(Xpos,Yhead);
  Image1->Canvas->MoveTo(Xpos,Yhead+4);
  Image1->Canvas->LineTo(Xpos+revers*L,Yhead+4);
  Image1->Canvas->Ellipse(Xpos+revers*L-Rhead2,Yhead+4-Rhead2,Xpos+revers*L+Rhead2,Yhead+4+Rhead2);
  Image1->Canvas->Ellipse(Xpos-Rhead,Yhead,Xpos+Rhead,Yhead-2*Rhead);
  Image1->Canvas->Rectangle(Xpos-H/2,Yhead-2*Rhead-1,Xpos+H/2,Yhead-2*Rhead-4);
  }
}
Для компонента Timer:
Draw();
if((Xpos >= Image1->Picture->Width-H) || (Xpos <= H))
revers = -revers;
Xpos = Xpos + revers * H;
num = 1 - num;
Draw();
Для нашей кнопки запуска анимации:
Timer1->Enabled = ! Timer1->Enabled;
Для нашей формы пишем следующее:
Image1->Canvas->MoveTo (0,Ypos+3);
Image1->Canvas->Pen->Width = 4;
Image1->Canvas->LineTo(Imagel->ClientWidth,Ypos+3);
Image1->Canvas->Pen->Width = 1;
Image1->Canvas->Pen->Mode = pmNotXor;
Draw();
Начнем анализ этого кода с конца - с последней процедуры FormCreate, являющейся обработчиком события OnCreate формы. В этой процедуре рисуется линия, отображающая «землю», по которой будет ходить наш человечек. Затем устанавливается режим пера pmNotXor. И в заключение вызывается процедура Draw, которая рисует исходное положение человечка.
 
Процедура ButtonClick является обработчиком события OnClick кнопки. Каждый щелчок на кнопке включает или выключает таймер, в результате чего человечек идет или останавливается.
 
Процедура Timer1Timer является обработчиком события OnTimer таймера. Это событие означает, что надо стереть прежний кадр и нарисовать новый. Сначала вызывается процедура Draw. Поскольку позиция человечка с момента показа предыдущего кадра не изменилась, то этот вызов рисует на том же самом месте, на котором рисовался предыдущий кадр. Следовательно, предыдущий рисунок стирается. Затем анализируется позиция человечка Xpos. Если эта позиция отстоит от какого-либо конца холста Image1 на величину, меньшую шага H, то изменяется на обратный знак переменной revers, характеризующей направление движения. Если revers = 1, человечек шагает вправо; если revers = -1, человечек шагает влево. Затем позиция Xpos изменяется на величину revers * H, т.е. на шаг вправо или влево. Изменяется переменная num, которая указывает номер высвечиваемого кадра: 0 или 1. В заключение вызывается процедура Draw, которая рисует указанный кадр в указанной позиции.
 
Последняя процедура, которую мы рассмотрим - процедура Draw, рисующая кадр. Она достаточно длинная, но в ней нет ничего сложного. В зависимости от значения num рисуется один или другой кадр, причем в рисунке учитывается позиция Xpos и направление движения revers.
 
Сохраните ваше приложение и выполните его. Щелкнув на кнопке вы можете заставить вашего человечка перемещаться. Достигнув края формы он будет поворачиваться и шагать в обратном направлении. При вторичном щелчке на кнопке он будет останавливаться.
Если заметили ошибку, выделите фрагмент текста и нажмите Ctrl+Enter

Добавить комментарий