Лабораторные работы по информатике для специальности «Моделирование и исследование операций в организационно-технических системах»
При изменении размеров формы необходимо модифицировать размер изображения находящегося в буфере, для чего необходимо внести следующие изменения в обработчик события OnResize.
procedure TfrmClock.FormResize(Sender: TObject); begin
//размер изображения в буфере
Buffer.Width:=ClientWidth;
Buffer.Height:=ClientHeight; //рассчитываем радиус циферблата
if ClientWidth>ClientHeight then r:=ClientHeight div 2-10 else r:=ClientWidth div 2-10;
//перерисовать окно
InvalidateRect(Handle, nil, False); end;{FormResize}
Внесите изменения в обработчик события OnPaint формы.
procedure TfrmClock.FormPaint(Sender: TObject); begin
//рисование изображения в буфер
ClockPaint(Buffer.Canvas);
//копирование содержимого буфера на холст формы
Canvas.Draw(0, 0, Buffer); end;{FormPaint}
Запустите программу, проверьте корректность ее работы.
Для формирования изображения можно использовать не только набор таких примитивов как линии и фигуры, но и изображения. Небольшие изображения, которые выводятся на другое изображение – фон, называются спрайтами. Вывод спрайтов можно осуществить несколькими способами. Начнем с самого простого из них – вывод спрайтов с помощью компонента TImage. Основной проблемой при выводе спрайтов является то, что растр содержащий спрайт имеет прямоугольную форму, а сам спрайт может иметь сложную форму. При выводе спрайта на изображение фона необходимо чтобы пикселы растра содержащего спрайт принадлежащие спрайту замещали пиксели фона, а остальные пикселы не изменяли бы фон (прозрачные пикселы). В компоненте TImage для работы со спрайтами удобно применять свойство Transparent (прозрачность). Если значение свойства равно True, то все пикселы, цвет которых совпадает с цветом пиксела находящегося в левом нижнем углу растра, будут прозрачными, т.е. при выводе изображения не будут копироваться (рисунок 3 и 4).
Создайте новый проект. На форму frmAirPlane поместите компонент TImage (Background). Загрузите в его свойство Picture изображение. Установите значение свойства AutoSize=True для компонента Background.
Поместите на форму еще один компонент TImage (Sprite). Загрузите в него изображение и установите значение свойства Transparent равным True, а значение (рисунок 4).
Поместите на форму таймер установите Interval=50 и создайте обработчик события
OnTimer.
...
var frmAirPlane: TfrmAirPlane;
Лабораторные работы по информатике для специальности «Моделирование и исследование операций в организационно-технических системах»
implementation var dx:Integer=10;
{$R *.dfm}
procedure TfrmAirPlane.TimerTimer(Sender: TObject); begin
//сдвигаем спрайт вправо
Sprite.Left:=Sprite.Left+dx;
//если достигли правой границы, то переходим в начало if Sprite.Left+Sprite.Width-20>ClientWidth then dx:=-dx; if Sprite.Left<0 then dx:=-dx;
end;{TimerTimer}
Рисунок 3 – Вывод спрайта, выведены все пикселы растра (cвойство Transparent=False).
Лабораторные работы по информатике для специальности «Моделирование и исследование операций в организационно-технических системах»
Рисунок 4 – Вывод спрайта, выведены только пикселы растра принадлежащие спрайту (свойство
Transparent=True)/
Запустите программу. Сразу видны недостатки такого способа создания анимации, а именно заметное мерцание во время воспроизведения анимации. Устранить такое мерцание не возможно, поэтому перейдем к рассмотрению более совершенных способов создания анимации.
Следующий способ вывода спрайтов основан на использовании маски для определения тех точек спрайта которые будут выводится при печати спрайта. Маска представляет собой черно-белое изображение спрайта. Черные точки находятся в тех местах спрайта, которые будут выводится, а белые в «прозрачных» местах спрайта. Алгоритм вывода спрайта следующий:
Выводится маска спрайта. Вывод осуществляется в режиме холста cmSrcAnd (свойство CopyMode). В этом режиме при копировании выводятся только пикселы имеющие черный цвет. Таким образом, в фоновом изображении вырезается область по форме спрайта (рисунок 5).
Рисунок 5 – Вывод маски спрайта
Далее по этим же координатам выводится изображение спрайта в режиме cmSrcPaint. В этом режиме пикселы спрайта выводятся только там, где цвет пикселов фона черный (рисунок 6). Таким образом, каждый спрайт состоит из двух изображений: маски спрайта и изображения спрайта.
Лабораторные работы по информатике для специальности «Моделирование и исследование операций в организационно-технических системах»
Рисунок 6 – Вывод спрайта
Рассмотрим пример программы использующий эту технику вывода спрайтов.
Создайте новый проект. На форму frmAirPlane поместите таймер Timer. Установите интервал срабатывания таймера равным 50 мс. В программе анимируется движение изображения самолета. Движение происходит по случайной траектории. Алгоритм работы программы очень прост и не нуждается в пояснениях. Полный текст программы приведен ниже.
Листинг 1
unit UPlane;
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, Jpeg, ImgList;
type
TfrmAirPlane = class(TForm) Timer: TTimer;
procedure FormCreate(Sender: TObject); procedure FormPaint(Sender: TObject); procedure TimerTimer(Sender: TObject); procedure FormDestroy(Sender: TObject);
private
{Private declarations } public
{Public declarations } Mask, //маска спрайта Sprite,//изображение спрайта
BackGround:TBitmap; //фон
x, y:Integer; //текущие координаты спрайта
//рисует сцену
procedure DrawScene(ACanvas:TCanvas); //рисование спрайта
procedure DrawSprite(x, y:Integer; ACanvas:TCanvas); //расчет координат спрайта
procedure CalcNewCoord(var newX, newY:Integer); //загрузка изображений
procedure LoadImages; end;
var frmAirPlane: TfrmAirPlane;
implementation
{$R *.dfm}
procedure TfrmAirPlane.FormCreate(Sender: TObject); begin
//двойная буферизация
Лабораторные работы по информатике для специальности «Моделирование и исследование операций в организационно-технических системах»
DoubleBuffered:=True; //загрузка изображений
LoadImages; //расчет координат
CalcNewCoord(x, y); end;{FormCreate}
procedure TfrmAirPlane.FormPaint(Sender: TObject); begin
//рисуем кадр
DrawScene(Canvas); end;{FormPaint}
procedure TfrmAirPlane.DrawScene; begin
with ACanvas do begin
//стираем фон
CopyMode:=cmSrcCopy;//режим копирования CopyRect(ClipRect, BackGround.Canvas,
BackGround.Canvas.ClipRect); //выводим спрайт
DrawSprite(x, y, ACanvas); end;{with}
end;{DrawScene}
procedure TfrmAirPlane.DrawSprite(x, y: Integer; ACanvas:TCanvas);
begin
with ACanvas do begin
//вывод маски спрайта CopyMode:=cmSrcAnd;//режим копирования для маски
Draw(x, y, Mask);
//вывод спрайта
CopyMode:=cmSrcPaint;//режим копирования для спрайта
Draw(x, y, Sprite); end;{with}
end;{DrawSprite}
procedure TfrmAirPlane.LoadImages; begin
//загрузка фона
BackGround:=TBitmap.Create; BackGround.LoadFromFile('background.bmp'); //загрузка маски спрайта
Mask:=TBitmap.Create; Mask.LoadFromFile('Mask.bmp'); //загрузка спрайта
Sprite:=TBitmap.Create; Sprite.LoadFromFile('Sprite.bmp');
end;{LoadImages}
procedure TfrmAirPlane.TimerTimer(Sender: TObject); begin
//расчет следующего положения спрайта
CalcNewCoord(x, y); //перерисовать изображение