Анимация на основе операции XOR

 

Первый способ основан на хитром свойстве логической операции XOR. Поместим на форму кнопку и объект Image1 с шириной, в два раза превышающей высоту. Сначала нарисуем небо – это мы уже умеем. Теперь надо нарисовать летающую тарелку. Их толком никто не видел, поэтому особой точности в деталях не требуется. Давайте вынесем команды рисования тарелки в отдельную процедуру, это заметно облегчит жизнь в дальнейшем.

 

PROCEDURE Ufo(x,y:INTEGER);

BEGIN

WITH Form1.Image1.Canvas DO

BEGIN

Pen.Color:=clBlue;

Pen.Width:=3;

Ellipse(x,y,x+20,y+10)

END

END;

 

Осталось организовать движение тарелки по экрану. Делается это в обработчике нажатия на кнопку примерно так:

 

Pen.Mode:=pmNOTXOR;

FOR i:=0 TO Image1.Width DO

BEGIN

Ufo(i, i DIV 2);

Application.ProcessMessages;

Sleep(10);

Ufo(i, i DIV 2)

END

END;

 

Самая важная строчка в этом фрагменте - Pen.Mode:=pmNOTXOR. Она устанавливает режим вывода графики "исключающее ИЛИ". При таком режиме вывод одной и той же картинки дважды в одно и то же место изображения приводит к автоматическому восстановлению фона под картинкой. Такой эффект основан на свойстве логической операции "исключающее ИЛИ": если a XOR b=c, то с XOR b=a. В цикле картинка выводится первый раз (вызов процедуры Ufo), затем выполняется команда Application.ProcessMessages, обеспечивающая немедленное отображение НЛО на экране и делается задержка на 10мс, чтобы мы успели увидеть, что получилось. Далее НЛО выводится в то же самое местоеще раз, при этом изображение тарелки пропадет, а под ней автоматически восстановится фон. Координаты тарелки меняются и по Х, и по Y, поэтому она поедет по экрану вправо вниз.

Запускаем… Красиво? Нет! Экран безобразно мерцает. Что делать? Спокойно, это просто еще один фокус Delphi. Чтобы динамическое изображение на форме не мерцало, в начало процедуры вывода анимации надо добавить строчку

 

Form1.DoubleBuffered:=TRUE;

 

Окончательный вариант обработчика имеет вид:

 

procedure TForm1.Button1Click(Sender: TObject);

 

var i:word;

 

begin

DoubleBuffered:=true;

with Image1.Canvas do

begin

Brush.Color:=clBlack;

FillRect(Image1.ClientRect);

for i:=1 to 500 do

Pixels[Random(Image1.Width),Random(Image1.Height)]

:=clWhite;

Pen.Mode:=pmNOTXOR;

FOR i:=0 TO Image1.Width DO

BEGIN

Ufo(i, i DIV 2);

Application.ProcessMessages;

Sleep(10);

Ufo(i, i DIV 2)

END

END

end;

 

Вот теперь наш мультик будет смотреться вполне неплохо, если бы не одна неприятность. Мы заказывали тарелку синего цвета (строчка Pen.Color:=clBlue), а получили желтого. Причина – в операции "исключающее ИЛИ". Она неизбежно искажает цвета выводимых на экран точек. Поэтому создать нормальную многоцветную анимацию таким способом затруднительно.