Работа с таймером

Буферизация фона

Воспользуемся способом №2, известным как "буферизация фона". Его идея даже проще – нужно перед отрисовкой каждого кадра запоминать фон под движущимся элементом картинки в отдельной переменной, а затем восстанавливать его. Наша летающая тарелка вписывается в прямоугольник с координатами (x,y) – (x+20,y+10). Чтобы запомнить такой фрагмент изображения, понадобится глобальная переменная типа TBitMap. Ее надо проинициализировать в начале работы программы (событие формы OnCreate) и удалить из памяти перед завершением работы (событие формы OnDestroy). Также введем константы UFOWidth и UFOHeight для хранения габаритных размеров перемещаемого фрагмента изображения и немного украсим нашу тарелку.

 

var Form1:TForm1;

mm:TBitMap;

 

const UFOWidth=20;

UFOHeight=10;

 

PROCEDURE Ufo(x,y:INTEGER);

 

begin

WITH Form1.Image1.Canvas DO

BEGIN

Pen.Color:=clBlue;

Brush.Color:=clWhite;

Pen.Width:=1;

Ellipse(x,y,x+UFOWidth,y+UFOHeight);

Pen.Color:=clRed;

MoveTo(x,y+UFOHeight DIV 2);

LineTo(x+UFOWidth,y+UFOHeight DIV 2)

END

END;

 

procedure TForm1.FormCreate(Sender: TObject);

begin

mm:=TBitMap.Create;

// задаем размеры буфера, равные размерам НЛО

mm.Width:=UFOWidth;

mm.Height:=UFOHeight

end;

 

procedure TForm1.FormDestroy(Sender: TObject);

begin

mm.Free

end;

 

Собственно отрисовка с буферизацией фона выполняется следующим образом:

 

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 1500 do

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

clWhite;

FOR i:=0 TO Image1.Width DO

BEGIN

// Запоминаем фрагмент в буфере

mm.Canvas.CopyRect(Rect(0,0,mm.Width,mm.Height),

Image1.Canvas,Rect(i,i DIV 2,i+UFOWidth,I DIV 2

+ UFOHEight));

// Рисуем НЛО

Ufo(i, i DIV 2);

// Ждем

Application.ProcessMessages;

Sleep(30);

// Восстанавливаем фон

Image1.Canvas.Draw(i,i DIV 2,mm);

END

END

end;

 

Метод C1.CopyRect(R1,C2,R2) копирует изображение, содержащееся в прямоугольнике R2 на холсте С2, в прямоугольник R1 на холсте С1. Разумеется, прямоугольники должны быть одинакового размера, хотя и могут находиться в разных частях холстов.

Метод C1.Draw(x,y,m) выводит изображение, хранящееся в переменной m типа TBitMap, на холст C1 в точке x,y.

В результате мы получили настоящую цветную анимацию в лучших диснеевских традициях, что и требовалось.

 

 

Интересная возможность Delphi – создание процедур, автоматически выполняющихся через заданные промежутки времени. Для этого используется специальный объект Timer (), находящийся на закладке System. Этот объект – невизуальный, он не отображается на форме во время работы программы и его можно разместить в любом ее месте.

Главное свойство объекта Timer называется Interval и задает время в миллисекундах, по истечении которого таймер вызывает процедуру, присоединенную к его событию OnTimer. Свойство Enabled включает и выключает таймер. Когда таймер включен, он постоянно и незаметно для пользователя отсчитывает время и, как только пройдет заданный интервал, выполняет заданную процедуру, затем снова начинает отсчитывать время и т.д.

Простейший пример работы таймера – вывод в заголовке формы текущего времени. Настроим таймер так, чтобы он вызывал процедуру каждую секунду. Для этого свойство Interval нужно установить в 1000, а свойство Enabled – в True. Обработчик события OnTimer имеет вид:

 

procedure TForm1.Timer1Timer(Sender: TObject);

 

begin

Form1.Caption:=TimeToStr(Now)

end;

Заставим наше НЛО мигать – менять цвет при движении – при помощи таймера. Настроим таймер так, чтобы он срабатывал каждые 100мс. Для управления цветом заливки НЛО придется ввести глобальную переменную clr, задав ей начальное значение clGreen

 

var clr:TColor=clGreen;

 

Обратите внимание на интересную особенность Delphi – глобальным переменным можно задавать начальные значения. В нашем случае в переменную clr с самого начала будет занесено значение clGreen (код зеленого цвета). TColor – это системный тип данных, предназначенный для хранения кодов цветов.

В процедуре таймера мы должны циклично менять значение переменной clr. Делается это так:

 

procedure TForm1.Timer1Timer(Sender: TObject);

begin

if clr=clGreen then

clr:=clRed

else

clr:=clGreen

end;

 

Здесь в переменную clr будут циклически заноситься то значение clGreen, то clRed.

Изменим процедуру Ufo, чтобы в ней использовалась переменная clr. Для этого заменим всего одну строчку на Brush.Color:=clr. Все! При запуске программы НЛО будет не только лететь по экрану, но и мигать то красным, то зеленым.

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