Розширений додатковий матеріал для вивчення теми "Комп'ютерна графіка Pascal"
Структура:
Створення динамічних зображень.
В попередніх заняттях було розглянуто прямолінійний рух кульки по вертикалі. В даному уроці розберемо дещо складніші рухи: діагональний рух, хаотичний рух.
Для початку пригадаємо алгоритми для вертикального руху. Розглядатимемо анімацію на прикладі алгоритму з копіюванням фрагменту екрана. В будь якому випадку, за допомогою процедури GetImage копіюється прямокутна область, що містить зображення. Для спрощення і універсальності алгоритму введемо додаткові змінні: h – висота, l – ширина зображення.
h=ymax-ymin; l=xmax-xmin;
Для нашого випадку розрахунки дадуть наступні результати:
h=100-0=100; l=100-0=100;
При копіюванні прямокутної області слід пам’ятати те, що й вставлятиметься також прямокутник. Координати, за яким здійснюється вставка – координати лівого верхнього кута прямокутної області. Для здійснення циклічного руху алгоритми матимуть наступний вигляд:
Згори вниз |
|
y:=y+a if y>=getmaxy-h then y:=0; |
Знизу вгору |
|
y:=y-a if y<=0 then y:=getmaxy-h; |
Зліва направо |
|
x:=x+a if x>=getmaxx-l then x:=0; |
Справа наліво |
|
x:=x-a if x<=0 then x:=getmaxx-l; |
Згори вниз - знизу вгору |
|
y:=y+a if (y>=getmaxy-h) or (y<=0) then a:= - a; |
Діагональний рух відмінний від горизонтального, чи вертикального тим, що в циклі одночасно змінюються обидві координати – x та y. Також слід звернути особливу увагу на умови зупинки циклу, чи повторення руху. Якщо задати початкові координати не являє великої складності, то кінцеві дещо складніше, так як екран у графічному режимі не квадратний – вісь 0X довша за вісь 0Y, а це означає, що для того, щоб точно досягти
правого нижнього кута потрібно вводити певні розрахункові коефіцієнти. Для спрощення розглянемо випадки, коли кулька (прямокутна область) дотикається одного з країв графічного екрану.
Згори зліва – вниз вправо |
|
x:=x+a; y:=y+b; if (y>=getmaxy-h) or (x>=getmaxx-l) then begin x:=0; y:=0; end; |
Згори справа – вниз вліво |
|
x:=x-a; y:=y+b; if (y>=getmaxy-h) or (x<=0) then begin x:=getmaxx-l; y:=0; end; |
Знизу зліва – вгору вправо |
|
x:=x+a; y:=y-b; if (y<=0) or (x>=getmaxx-l) then begin x:=0; y:= getmaxy-h; end; |
Знизу справа – вгору вліво |
|
x:=x-a; y:=y-b; if (y<=0) or (x<=0) then begin x:= getmaxx-l; y:= getmaxy-h; end; |
Згори зліва – вниз вправо циклічно |
|
x:=x+a; y:=y+b; if (y>=getmaxy-h) or (x>=getmaxx-l) then begin a:=-a; b:=-b; end; if (y<=0) or (x<=0) then begin a:=-a; b:=-b; end; |
Згори справа – вниз вліво циклічно |
|
x:=x-a; y:=y+b; if (y>=getmaxy-h) or (x>=getmaxx-l) then begin a:=-a; b:=-b; end; if (y<=0) or (x<=0) then begin a:=-a; b:=-b; end; |
Код програми: program diagonal; uses crt,graph; const r=50; var gd,gm:integer;
Page:byte; size:integer;bitmap:pointer;
xc,yc,x,y,a,b:integer; begin gd:=vga;gm:=vgamed;
InitGraph (gd,gm,'..\bgi'); xc:=getmaxx div 2; yc:=getmaxy div 2;
SetColor (yellow); SetFillStyle(1,yellow); x:=0;y:=0; Circle (xc,yc,r); FloodFill(xc,yc,yellow); size:=imagesize (xc-r,yc-r,xc+r,yc+r); getmem(bitmap,size); getimage(xc-r,yc-r,xc+r,yc+r,bitmap^); a:=15; b:=10; repeat
SetActivePage (Page);
ClearDevice; putimage(x,y,bitmap^,1);
SetVisualPage (Page);
Page:=1-Page; Delay (150); x:=x+a; y:=y+b; if (y>=getmaxy-2*r) or (y<=0) or (x>=getmaxx-2*r) or (x<=0) then begin a:=-a; b:=-b; end;
Until keypressed; CloseGraph; end.
Для здійснення хаотичного руху кульки, яка відбивається від усіх стінок можна використати попередній алгоритм, дещо його підкорегувавши. При зіткненні кульки з лівою або правою межею екрану кулька має змінити напрямок на протилежний, відносно даної межі. Це саме стосується і верхньої та нижньої меж:
x:=x+a; y:=y+b; if (y>=getmaxy-2*r) or (y<=0) then b:=-b; if (x>=getmaxx-2*r) or (x<=0) then a:=-a;
Код програми: program billiard; uses crt,graph; const r=50; var gd,gm:integer;
Page:byte; size:integer;bitmap:pointer;
xc,yc,x,y,a,b:integer; begin gd:=vga;gm:=vgamed;
InitGraph (gd,gm,'..\bgi');
xc:=getmaxx div 2; yc:=getmaxy div 2;
SetColor (yellow); SetFillStyle(1,yellow);
x:=xc;y:=0;
Circle (xc,yc,r);
FloodFill(xc,yc,yellow);
size:=imagesize (xc-r,yc-r,xc+r,yc+r);
getmem(bitmap,size); getimage(xc-r,yc-r,xc+r,yc+r,bitmap^); a:=15; b:=10; repeat
SetActivePage (Page); ClearDevice; putimage(x,y,bitmap^,1);
SetVisualPage (Page);
Page:=1-Page; Delay (150); x:=x+a; y:=y+b; if (y>=getmaxy-2*r) or (y<=0) then b:=-b; if (x>=getmaxx-2*r) or (x<=0) then a:=-a;
Until keypressed; CloseGraph; end.