Например, если в режиме ORPut на малиновый цвет изображения (номер 5, двоичная запись 0101) вывести бирюзовый (номер 3, 0011) из буфера, то результирующая картинка будет светло-серого цвета (номер 7, 0111). Из этих пяти режимов самым интересным является XOR, поскольку проведенные последовательно две операции XOR с одинаковым вторым аргументом оставляют первый из них без изменений. Это свойство операции XOR и используется в тех случаях, когда необходимо изобразить некий подвижный объект на сложном
- 453 -
фоне: два раза выведя один и тот же фрагмент в одно и то же место в режиме XOR, мы оставим фон неизменным. Фактически, мы таким образом экономим память ПЭВМ — не нужен буфер для запоминания участка фона, находившегося под новой картинкой (рис. 19.29).
| Graph, CRT; { используются Graph и CRT }
| {$I initgraf.pas} { процедура инициализации }
| CONST
| r = 10; { радиус подвижного шарика }
| VAR
| X1, Y1, X2, Y2, sx, sy : Integer; { Переменные для ожи- }
| maxx, maxy, sxmove, symove: Integer; { вления фрагмента }
| Size : Word; { размер фрагмента }
| P : Pointer; { указатель на буфер }
| BEGIN
| GrInit; { инициализация графики }
| maxx := GetMaxX; { максимальное поле экрана }
| maxy := GetMaxY;
| X1 := maxx div 2 - r; { Координаты области экрана, }
| Y1 = maxy div 2 - r; {в которой будет нарисован }
| X2 = Х1 + 2*r; { шарик и которая и будет со- }
| Y2 = Y1 + 2*r; { храненным фрагментом }
| sx = Х1; sxmove := 3; { Начальная точка движения и }
| sy := Y1; symove := -1; { шаг перемещения шарика }
| SetFillStyle( SolidFill, Red ); { выбор типа заливки }
| PieSlice( X1+r,Y1+r, 0,360, r ); { рисование шарика }
| Size := ImageSize(X1,Y1,X2,Y2); { фрагмент в байтах }
| GetMem(P, Size ); { размещение буфера }
| Getlmage( Х1, Y1, Х2, Y2, P^); { фрагмент -> в буфер }
| SetFillStyle(CloseDotFill, Blue); { тип заливки фона }
| Bar( 50, 50, maxx-50, maxy-50 ); { фоновая картинка }
| repeat { Начинается движение шарика: }
| PutImage( sx, sy, P^, XORPut ); { вывод шарика }
| Delay( 12 ); { пауза для АТ/12МГц }
| Putlmage( sx, sy, P^, XORPut ); { стирание шарика }
| {ограничения на движение шарика в пределах поля фона: }
| if (sx<50) or (sx>maxx-50-2*r) then
| sxmove := -sxmove;
| if (sy<50) or (sy>maxy-50-2*r) then
| symove := -symove;
| Inc( sx, sxmove ); {Следующая точка появления }
| Inc( sy, symove ); { шарика на экране }
| until KeyPressed; { ... пока не нажата клавиша }
| FreeMem( Р, Size ); { освобождение памяти буфера }
| CloseGraph { закрытие режима графики }
| END.
Рис. 19.29
- 454 -
В приведенном примере продемонстрирован алгоритм мультипликации, применяющий «битовые» методы (используется пересылка битовых массивов процедурами GetImage и PutImage). Скорость движения картинки сильно зависит от разрешения экрана и количества цветов: наибольшая — в режиме CGA 640x200 2 цвета (1 бит на пиксел), наименьшая — в режиме VGA 320x200 256 цветов (8 бит на пиксел). Возникают также некоторые сложности с синхронизацией перемещений и частоты вертикальной развертки монитора.
Обращаем внимание на стандартную связку:
Size:= ImageSize( Х1, Y1, Х2, Y2 ); { фрагмент в байтах }
GetMem( P, Size ); { размещение буфера }
GetImage( Х1, Y1, Х2, Y2, P^ ); { фрагмент -> в буфер }
...
Putlmage( х, у, P^, xxxPut ); { вывод фрагмента(ов) }
FreeMem( P, Size); { освобождение буфера }