Выкарыстанне бітавых вобразаў дазваляе абыходзіцца толькі адным кампанентам 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);
}
|
Дадатак у час працы:

|