Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Информатика программирование, учебник.doc
Скачиваний:
1
Добавлен:
01.04.2025
Размер:
22.08 Mб
Скачать

5 Анимация изображений

Программы, которые строят, перемещают, изменяют форму различных изображений на экране в соответствии с заранее разработанным сценарием, называются анимационными. Хорошо продуманный, увязанный с возможностями ПК (характеристиками адаптера монитора, быстродействием, наличием и объемом внешних носителей) сценарий - основа любой анимационной программы. Анимационные программы, как правило, требуют применения довольно сложных алгоритмов и часто используют большой объем данных. Данные, на основании которых осуществляется движение логически выделенных (например, сюжетом игры) фигур или их фрагментов. Для "оживления" графических рисунков используют самые различные ухищрения, некоторые из них будут рассмотрены в данном параграфе.

Анимационные программы работают с двумя классами объектов: спрайтами и средой. Спрайтом называют логически законченный движущийся элемент изображения на экране. Среда - это фон, по которому происходит движение спрайта. Существует много различных способов заставить спрайт двигаться. Все они подразделяются на две группы: комбинационные и морфологические.

В основе комбинационных методов лежат различные модификации следующего алгоритма: вывести вариант спрайта на экран; стереть спрайт; вывести с некоторым перемещением другой вариант спрайта и т.д. Программа в соответствии с алгоритмом выводит варианты спрайта, как бы перемещая по экрану. Так как этот процесс происходит быстро, то для инерционного человеческого глаза создается полная иллюзия непрерывного движения.

Морфологические методы анимации манипулируют спрайтами на основе выполнения одного или нескольких правил. Наиболее эффективно они реализуются средствами объектно-ориентированного программирования, поэтому в рамках этой книги мы их рассматривать не будем.

5.1 Дублирования спрайта цветом фона

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

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

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

Рис. 3.17 Атом - ядро и орбиты двух электронов

Алгоритм программы:

  • Перевести монитор в графический режим.

  • Найти координаты центра экрана X и Y.

  • Найти величины xasp и yasp для корректировки изображения.

  • В цикле строить ядро и две орбиты атома (см. процедуру ORBIT). Выход из цикла при нажатии любой клавиши.

Program PR27;

Uses CRT, GRAPH;

Const RA=12; CA=11; {Радиус и цвет ядра атома}

Var n, r, X, Y : integer;

drivervar, modevar: integer;

xasp, yasp : word;

Procedure ORBIT(C: INTEGER);

Begin

setcolor (CA); {РИСУЕМ (ВОССТАНАВЛИВАЕМ) ЯДРО}

circle (X, Y, RA);

SetFillStyle(11, CA); FloodFill(X, Y, CA);

setcolor (C); {РИСУЕМ ОРБИТЫ ЗАДАННЫМ ЦВЕТОМ}

ellipse (X,Y,0,360,r,100*round(xasp) div yasp);

ellipse (X,Y,0,360,100,r*round(xasp) div yasp);

delay(200); {ВРЕМЕННАЯ ЗАДЕРЖКА ДЛЯ ФИКСАЦИИ ПОЛОЖЕНИЯ ОРБИТ}

setcolor (black); {Рисуем орбиты цветом фона}

ellipse (X,Y,0,360,r,100*round(xasp) div yasp);

ellipse (X,Y,0,360,100,r*round(xasp) div yasp)

End;

Begin

drivervar := detect;

initgraph (drivervar, modevar, 'd:\tp\bgi');

X:=GetMaxX div 2; Y:=GetMaxY div 2; {ВЫЧИСЛЕНИЕ КООРДИНАТ ЦЕНТРА}

getaspectratio(xasp, yasp);

r:=0; setbkcolor(black); cleardevice;

while not keypressed {ДЕЛАЕМ ДО НАЖАТИЯ ЛЮБОЙ КЛАВИШИ}

do begin

for n:=0 to 50

do Begin

ORBIT(15); {БЕЛЫЕ ОРБИТЫ ЭЛЕКТРОНОВ}

r:=r+2 {ЭЛЛИПС ОРБИТ РАСШИРЯЕТСЯ}

End;

for n:=50 downto 0

do Begin

r:=r-2; {ЭЛЛИПС ОРБИТ СУЖАЕТСЯ}

ORBIT(14) {ЖЕЛТЫЕ ОРБИТЫ ЭЛЕКТРОНОВ}

End

End;

CloseGraph {ЗАКРЫТИЕ ГРАФИЧЕСКОГО ВИДЕОРЕЖИМА}

End.

В качестве второго примера иллюстрирующего рассматриваемый метод возьмем известную демонстрационную программу, получившую ласковое название – “Спиралька”.

Пример 28. Заставка с щадящим режимом работы монитора. По черному экрану монитора по восьмеркам относительно центра перемещается спираль, меняющая размеры и цвет во времени (см. фрагмент на рис. 3.18).

Рис. 3.18 Полет пружинки

Program PR28;

Uses Graph, CRT;

CONST R1=200; KOL=30;

VAR

X, Y, R: ARRAY [1..KOL] OF INTEGER;

N,V,M,X1,Y1,I,J: INTEGER;

A, B: REAL;

Procedure GrInit; {ИНИЦИАЛИЗАЦИЯ РЕЖИМА ГРАФИКИ}

Var GraphDriver: Integer; {ДЛЯ ГРАФИЧЕСКОГО АДАПТЕРА}

GraphMode : Integer; {ДЛЯ ГРАФИЧЕСКОГО РЕЖИМА}

ErrorCode : Integer; {ДЛЯ КОДА ОШИБКИ}

Begin

GraphDriver:= Detect; {РЕЖИМ АВТО ОПРЕДЕЛЕНИЯ}

InitGraph(GraphDriver, GraphMode, 'D:\tp\bgi'); {ИНИЦИАЛИЗАЦИЯ}

End;

Begin GrInit;

FOR I:=1 TO KOL DO BEGIN X[I]:=0 ; Y[I]:=0 ; R[I]:=0 END;

SETFILLSTYLE(1,0); BAR(1,1,640,480); A:=1 ;

REPEAT

V := RANDOM(4)+0;

FOR M := 1 TO 10

DO BEGIN

R[1]:= TRUNC(40*COS(1.0*A*PI/180)); {РАДИУС КОЛЬЦА}

X[1]:= TRUNC(R1*COS(1.5*A*PI/180/1))+300; {Координата центра X}

Y[1]:= TRUNC(R1*SIN(1.0*A*PI/180/1))+250; {Координата центра Y}

FOR J:=2 TO KOL {РИСУЕМ КОЛЬЦА}

DO BEGIN

I:=KOL-J+2; X[I]:=X[I-1]; Y[I]:=Y[I-1]; R[I]:=R[I-1];

SetColor(I DIV 5 +8); {МЕНЯЕМ ЦВЕТ КОЛЕЦ}

ELLIPSE(X[I],Y[I],0,360,60+0*R[I],60+R[I]);

if keypressed then Exit

END;

SetColor(0); {ПОВТОРНО РИСУЕМ КОЛЬЦА ЦВЕТОМ ФОНА}

ELLIPSE(X[KOL],Y[KOL],0,360,60+0*R[KOL],60+R[KOL]);

A := A + V

END

UNTIL KEYPRESSED {НАЖАТИЕ ЛЮБОЙ КЛАВИШИ - КОНЕЦ ПРОГРАММЫ}

END.

В качестве третьего примера иллюстрирующего рассматриваемый метод возьмем программу изображающую зимний пейзаж. Падающий снег, сугробы и заснеженный домик в ночи.

Пример 29. Смоделировать падение 500 снежинок на землю и крышу дома (см. рис. 3.19).

Рис. 3.19 Заснеженный домик

Ниже приведен код программы. Положение снежинок фиксируется с помощью их координат, хранимых в одномерных массивах x[i] и y[i].

Program PR29; {BOBKOV ANDREW, ГРУППА ИС-11}

uses crt, graph;

const N=500; {ЧИСЛО СНЕЖИНОК}

var key: char;

GrDriver, GrMode: integer;

i,x1,y1:integer;

st: boolean;

x, y: array[1..n] of integer;

procedure DOM;

begin

setColor(8); setFillStyle(11,8); SetLineStyle(0,3,3);

line(200,250,200,298); line(210,250,210,285); {ТРУБА}

line(210,250,205,245); line(200,250,205,245);

SetColor(6); SetLineStyle(0,3,3); SetFillStyle(2,15);

Bar(200, 300, 400, 480); {Стены домика}

line(180,315,300,200); line(420,315,300,200); {СКАТЫ КРЫШИ}

SetFillStyle(8,14); Bar(265,400,330,350); {ОКНО ДОМА}

SetColor(12); circle(300,250,10); {ЧЕРДАЧНОЕ ОКНО}

SetColor(7);

rectangle(-2,-2,GetMaxX+2,GetMaxY) {РАМКА, ВИДНА КАК ЗЕМЛЯ}

end;

begin

initGraph(GrDriver,GrMode,'d:\tp\bgi');

DOM; {Построение домика}

randomize;

for i:= 1 to n {ГЕНЕРАЦИЯ КООРДИНАТ 500 СНЕЖИНОК}

do begin

X[i]:=random(GetMaxX); Y[i]:=random(GetMaxY);

end;

repeat {Имитация падающего снега. Бесконечный цикл}

for i:= 1 to n {ДЛЯ КАЖДОЙ ИЗ 500 СНЕЖИНОК ДЕЛАЕМ}

do begin

if y[i]<GetMaxY

then begin {ОПРЕДЕЛЕНИЕ НОВЫХ КООРДИНАТ СНЕЖИНКИ}

st:=false; x1:=x[i]; y1:=y[i];

if getPixel(x[i],y[i]+1)=0

then begin inc(Y[i],1) end

else begin

if GetPixel(x[i]+1,y[i]+1)=0

then begin inc(x[i]); inc(y[i]) end

else begin

if GetPixel(x[i]-1,y[i]+1)=0

then begin dec(x[i]); inc(y[i]) end

else begin {ПОЯВЛЕНИЕ НОВОЙ СНЕЖИНКИ}

x[i]:=random(GetMaxX); y[i]:=0; st:= true

end

end

end;

if not st then PutPixel(x1,y1,0); {Стираем снежинку}

PutPixel(x[i],y[i],15) {Отображаем снежинку на новом

месте}

End

else begin PutPixel(x[i],y[i],15);

y[i]:=0; x[i]:=random(GetMaxX) {Появление новой

Снежинки}

end

end;

until KeyPressed;

setbkcolor(3); {Утро}

setfillstyle(1,14); FillEllipse(100,100,40,40); {СОЛНЦЕ}

repeat {Имитация таяния снега}

for i:= 1 to n

do begin

if y[i]<GetMaxY

then begin

st:= false; x1:=x[i]; y1:=y[i];

if GetPixel(x[i],y[i]+1)=0 then begin inc(Y[i],1) end

else begin

if GetPixel(x[i],y[i]+1)=15

then begin inc(y[i],1);

PutPixel(x[i],y[i],0); y[i]:=0;

x[i]:=random(GetMaxX)

end

else if GetPixel(x[i]+1,y[i]+1)=15

then begin

inc(x[i]);inc(y[i]);PutPixel(x[i],y[i],0);

x[i]:=random(GetMaxX); y[i]:=0

end

else if GetPixel(x[i]-1,y[i]+1)=15

then begin

dec(x[i]); inc(y[i]);

PutPixel(x[i],y[i],0);

x[i]:=random(GetMaxX); y[i]:=0

end

else begin PutPixel(x[i],y[i],0);

x[i]:=random(GetMaxX); y[i]:=0

end

end

end

else begin x[i]:=random(GetMaxX); y[i]:=0 end

end

until KeyPressed;

CloseGraph

end.