Использование битовых образов позволяет обходиться только одним компонентом Image на форме. При срабатывании таймера объект, хранящийся в виде битового образа, будет прорисовываться поверх фона.
Однако прорисовка поверх имеющегося изображения испортит рисунок фона. Поэтому перед прорисовкой следует скопировать ту часть фона, поверх которой будет выведен объект, в битовый образ. А при следующем срабатывании таймера следует восстановить фон.
Алгоритм для реализации такой анимации будет следующим:
- Сохранить часть фона.
- Нарисовать объект.
- Запустить таймер.
- Пока таймер работает:
4.1. восстановить фон; 4.2. рассчитать новое положение объекта; 4.3. сохранить часть фона; 4.4. нарисовать объект.
Пример 17.13. Создать проект, в котором луна будет летать вокруг земли.
Этапы выполнения задания
- Поместить на форму компонент Image, компоненты Timer и Button.
- Изменить свойства Caption у компонента Button1 на «Старт».
- Установить значение false у свойства таймера Enabled.
- Установить в инспекторе объектов время срабатывания таймера равным 100.
- Описать три переменных для хранения битовых образов: fon — для хранения фонового изображения, kadr — для хранения изображения луны, fon_kadr — для хранения части фона.
- Написать обработчик события OnCreate для формы, в котором:
6.1. Загрузить из файла изображение земли в битовый образ fon и компонент Image1. 6.2. Загрузить из файла изображение луны в битовый образ kadr. Описать начальное положение луны. 6.3. Определить прямоугольные области для текущего положения на фоне и для кадра.
- Написать обработчик события OnClick для компонента Button1, в котором необходимо запустить таймер.
- Написать обработчик события OnTimer, в котором следует реализовать анимацию движения луны. Луна двигается по эллиптической орбите.
Пример 17.14*. Создать проект в котором бабочка будет летать вокруг цветка по траектории в виде астроиды и менять свое направление полета.
Этапы выполнения задания
- Анимация запускается сразу при загрузке формы (без кнопки запуск).
- Если не учитывать необходимость смены направления бабочки при полете, то задание аналогично примеру 17.13 (достаточно изменить формулы определяющие точки окружности на формулы определяющие точки астроиды — пример 15.11). Поэтому рассмотрим только смену направления полета.
- Направление будем менять, когда значение переменной t изменится на значение т. е. в значениях: . Переменная будет определять, где в текущий момент времени находится бабочка. Значение переменной ρ определим следующим образом:
p =
- С помощью логической переменной f будем определять нужен ли поворот изображения в текущей точке.
- Если поворот нужен, то для четных значений p бабочка отражается слева-направо, а для нечетных — сверху-вниз.
|
Пример 17.13. Форма на этапе проектирования:
Глобальные переменные:
Graphics::TBitmap
*kadr = new Graphics::TBitmap(),
*fon = new Graphics::TBitmap(),
*fon_kadr = new Graphics::TBitmap();
int w, h, x_luna, y_luna,
x_c = 180, y_c =130,
R_x = 155, R_y =130;
TRect pr_kadr, pr_fon;
double t = 0
|
Обработчик события OnClick для компонента Button1.
void __fastcall TForm1:: Button1Click(TObject *Sender)
{
Timer1 ->Enabled = true;
}
|
Обработчик события OnCreate для формы.
void __fastcall TForm1:: FormCreate(TObject *Sender)
{
//загрузка изображений
fon -> LoadFromFile("земля.bmp");
Image1 -> Picture -> Assign(fon);
kadr -> LoadFromFile("луна.bmp");
w = kadr -> Width;
h = kadr -> Height;
kadr -> Transparent = true;
//определение битового образа
//для хранения части фона
fon_kadr -> Width = w;
fon_kadr -> Height = h;
pr_kadr = Bounds(0, 0, w, h);
//начальное положение луны
x_luna = 180;
y_luna = 2;
//сохранение части фона под луной
pr_fon = Bounds(x_luna, y_luna, w, h);
fon_kadr -> Canvas -> CopyRect
(pr_kadr, fon -> Canvas, pr_fon);
//рисование луны
Image1 -> Canvas -> Draw
(x_luna, y_luna, kadr);
pi = acos(-1);
} |
Обработчик события OnTimer для таймера.
void __fastcall TForm1:: Timer1Timer(TObject *Sender)
{
//восстановление фона
Image1 -> Canvas -> Draw
(x_luna, y_luna, fon_kadr);
//расчет координат эллипса
t += 0.1;
if (t > 2 * pi)
t = 0;
x_luna = x_c + ceil(R_x * sin(t));
y_luna = y_c - ceil(R_y * cos(t));
//сохранение части фона
pr_fon = Bounds(x_luna, y_luna, w, h);
fon_kadr -> Canvas -> CopyRect
(pr_kadr, fon -> Canvas, pr_fon);
//рисование луны
Image1 -> Canvas -> Draw
(x_luna, y_luna, kadr);
}
|
Работающее приложение:
Пример 17.14. Обработчик события OnTimer для таймера.
void __fastcall TForm1::Timer1Timer (TObject *Sender)
{
//восстановление фона
Image1 -> Canvas -> Draw
(x_fly, y_fly, fon_kadr);
t += 0.1;
if (t > 2 * pi)
t = 0;
//определение четверти, в которой
//находится бабочка и
//смена ее при необходимоси
if (t < pi / 2){
if ( p != 0){
p = 0;
f = true;
}
}
else
if (t < pi) {
if (p != 1 ){
p = 1;
f = true;
}
}
else
if (t < 3 * pi /2){
if (p != 2){
p = 2;
f = true;
}
}
else
if (p != 3){
p = 3;
f = true;
}
//отражение бабочки
if (f){
f = false;
pr_fly = pr_kadr;
switch (p){
case 0: case 2:{
pr_fly.left = pr_kadr.right;
pr_fly.right = pr_kadr.left;
break;
}
case 1: case 3:{
pr_fly.top = pr_kadr.bottom;
pr_fly.bottom = pr_kadr.top;
break;
}
}
kadr -> Canvas -> CopyRect
(pr_fly, kadr -> Canvas, pr_kadr);
}
//расчет координат астроиды
x_fly = x_c + R_x * cos(t) * cos(t) * cos(t);
y_fly = y_c - R_y * sin(t) * sin(t) * sin(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);
}
|
Работающее приложение.
|