Работа с таймером
Буферизация фона
Воспользуемся способом №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. Все! При запуске программы НЛО будет не только лететь по экрану, но и мигать то красным, то зеленым.
Применение нескольких таймеров позволяет организовать синхронную анимацию нескольких объектов. Например, можно создать несколько блуждающих по экрану астероидов, от которых должна увертываться управляемая пользователем летающая тарелка.