В этом проекте мы изучаем обработчики событий и некоторые способы работы с графическими объектами.
На форму ставится компонент Image1:TImage. Он используется для загрузки мишени из файла и для
перемещения мишени во время игры. Компонент Timer задает моменты времени, в которые
Image1 ( и мишень) занимает новое положение. Новые координаты (Left,Top) для Image1 вычисляются так:
Image1.Left := random(xmax); Функция Random генерирует целые случайные числа (в диапазоне 0..xmax-1).
Xmax вычисляется из расчета, чтобы окно Image1 не выходило за пределы клиентской части формы. Клиентская часть - то часть формы, на которой можно ставить компоненты, рисовать. Т е исключается заголовок (Caption) и обрамление. Можете посмотреть в инспекторе значения Width и ClientWidth для формы - отличие около 8 пиксел, т е это рамочка. А Height больше чем ClientHeight на 20-40 пиксел.
ymax вычисляется аналогично. Xmax и ymax вычисляются в начале работы проекта, когда появляется форма (см текст процедуры FormShow) и, естественно, перевычисляются при изменении размеров формы (проц. FormResize).
Кстати, в FormResize предотвращаются слишком малые размеры формы:
if ClientWidth < 610 then width:= 615;
Заодно поясним, что ClientWidth и Form1.ClientWidth - это одно и то же, т е внутри описания класса TForm1 имя объекта Form1 можно не указывать.
Однако, вернемся к процедуре FormShow, которая выполняется при старте проекта.
После вычисления xmax, ymax она создает объект BM для работы с картинкой мишени.
BM := TBitmap.Create;
Как видите, для создания объекта известного класса достаточно объявить переменную этого класса
и присвоить ей результат работы процедуры Create(создать) этого класса. Потому что описание класса
хранящееся в Делфи есть как бы рабочие чертежи, по которым можно создать объект.
Далее этот объект BM, используя свой метод (т е процедуру) LoadFromFile загружает картинку из файла на диске.:
BM.LoadFromFile('mishen3.bmp'); //загружаю его картинкой (мишень) из файла
BM.Transparent:= true; // объект прозрачный
BM.TransparentMode:= tmAuto; //прозрачный цвет взять в пикселе [0,0]
Image1.Canvas.Draw(50,50,BM); //рисую на поверхности Canvas картинку BM, т е мишень
Рассмотрим работу компонента Timer1. Нужно поставить его на форму с палитры компонентов.
При работе проекта: если свойство Timer1.Enabled = true, то объект активен. Это проявляется в том, что каждые Timer1.Interval (миллисекунд) выполняется процедура - обработчик события onTimer. В нашем проекте это Timer1Timer. Как уже было сказано, вычисляются и устанавливаются новые координаты объекта Image1, в результате чего мишень появляется в новом месте. Затем запускается процедура TrackBar1Change - обработчик события: изменилось состояние (настройка) объекта TrackBar1. Ниже займемся этим TrackBar1, а пока отметим, что имеется кнопка (Вкл/выкл) обработчик щелчка которой (btnTimerClick) выключает и включает таймер и, следовательно прыжки мишени - при помощи оператора:
Timer1.Enabled := not Timer1.Enabled;
Объект TrackBar1: TTrackBar; - используется в качестве графического регулятора какой-либо величины. В нашем проекте - TrackBar1 регулирует время, в течение которого мишень неподвижна (потом она прыгает в другое место), более конкретно - регулирует Timer1.Interval. Если изменить положение движка регулятора TrackBar1, то сработает процедура TrackBar1Change, а в ней записаны следующие операторы:
procedure TForm1.TrackBar1Change(Sender: TObject); begin Timer1.Interval := Round(5000/TrackBar1.Position); // Timer1.Interval вычисляется в зависимости от TrackBar1.Position sb1.SimpleText := 'Уровень = '+ IntToStr(TrackBar1.Position) + ' (пауза = ' + floattostr(Timer1.Interval/1000) + ' сек )'; // выводится сообщение в sb1 (TStatusBar) end;sb1 - это объект класса TStatusBar - полоска в нижней части формы, куда обычно записывают сообщения о состоянии проекта.
Игрок должен поражать мишень. Для этого он наводит мышкурсор (крест) на центр мишени и нажимает левую мышкнопку. Если курсор находится в окне объекта Image1 (об этом свидетельствует форма курсора - крест), то срабатывает процедура-обработчик Image1MouseDown. Вот ее текст:
procedure TForm1.Image1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer); //Происходит при нажатии мышкнопки
// в параметрах передаются координаты мышкурсора, нажатая мышкнопка,
// нажатость спецклавиш (Alt, Shift, Ctrl )
var ocki: double; ball,ii,jj: Integer; bus: String;
begin
beep; // звук выстрела.
inc(count); // счетчик выстрелов увеличим на 1
bus:= ' '; // чтобы двигалось число в Caption
ocki:= sqrt(sqr(x-121) + sqr(y-121)); //расстояние от центра мишени.
if ocki <= 7 then ball:=10 else ball:= trunc(-9/63*ocki+11);
// вычислим : сколько очков дал выстрел.
if ball < 0 then ball:=0;
if count <= 10 then
begin inc(suma,ball); // суммируем (накапливаем) баллы выстрелов.
for ii:= 1 to 20 do // чтобы двигалась оценка выстрела в Caption
begin delete(bus,1,1); // удаляю из строки bus 1-й символ
sleep(20); // пауза 20 миллисекунд (чтобы замедлить процесс)
Caption := bus + IntToStr(ball);
// в Caption помещаю эту стриженую строку пробелов,
// а справа цепляю оценку выстрела. (длина строки меняется)
end;
if count = 10 then // т е конец игры
begin
Caption := ' ' + IntToStr(suma) + ' очков (10 выстрелов)';
Timer1.Enabled := false; // отключаю работу таймера.
end;
end;
end;
В ней достаточно комментариев. Дополнительно отмечу следующее:
Рисование фона формы выполено за счет:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls, ComCtrls;
type
TForm1 = class(TForm)
Timer1: TTimer;
btnTimer: TButton;
Image1: TImage;
TrackBar1: TTrackBar;
btnRepeat: TButton;
sb1: TStatusBar;
Label1: TLabel;
procedure btnTimerClick(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
procedure FormShow(Sender: TObject);
procedure TrackBar1Change(Sender: TObject);
procedure Image1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure btnRepeatClick(Sender: TObject);
procedure FormResize(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure FormPaint(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
var BM,BM_fon: TBitmap; xmax, ymax: Integer; count: integer = 0;
suma: integer =0;
procedure TForm1.btnTimerClick(Sender: TObject);
begin
Timer1.Enabled := not Timer1.Enabled;
end;
procedure TForm1.Timer1Timer(Sender: TObject);
begin
{Перемещает мишень, изменяя координаты верхне-левого угла
(Left, Top) объекта Image1}
Image1.Left := random(xmax);
Image1.Top := random(ymax);
TrackBar1Change(Sender); //Запускает процедуру TrackBar1Change
end;
procedure TForm1.FormShow(Sender: TObject);
begin
xmax := ClientWidth - 280; //верхний предел изменения координаты Image1.Left
// (см Timer1Timer)
ymax := ClientHeight - 320; //верхний предел изменения координаты Image1.Top
BM := TBitmap.Create; //создаю объект BM класса TBitmap.
BM.LoadFromFile('mishen3.bmp'); //загружаю его картинкой (мишень) из файла
BM.Transparent:= true; // объект прозрачный
BM.TransparentMode:= tmAuto; //прозрачный цвет взять в пикселе [0,0]
Image1.Canvas.Draw(50,50,BM); //рисую на поверхности Canvas картинку BM
end;
procedure TForm1.TrackBar1Change(Sender: TObject);
begin
Timer1.Interval := Round(5000/TrackBar1.Position);
// Timer1.Interval вычисляется в зависимости от TrackBar1.Position
sb1.SimpleText := 'Уровень = '+ IntToStr(TrackBar1.Position) +
' (пауза = ' + floattostr(Timer1.Interval/1000) + ' сек )';
// выводится сообщение в sb1 (TStatusBar)
end;
procedure TForm1.Image1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer); //Происходит при нажатии мышкнопки
// в параметрах передаются координаты мышкурсора, нажатая мышкнопка,
// нажатость спецклавиш (Alt, Shift, Ctrl )
var ocki: double; ball,ii,jj: Integer; bus: String;
begin
beep; // звук выстрела.
inc(count); // счетчик выстрелов увеличим на 1
bus:= ' '; // чтобы двигалось число в Caption
ocki:= sqrt(sqr(x-121) + sqr(y-121)); //расстояние от центра мишени.
if ocki <= 7 then ball:=10 else ball:= trunc(-9/63*ocki+11);
// вычислим : сколько очков дал выстрел.
if ball < 0 then ball:=0;
if count <= 10 then
begin inc(suma,ball); // суммируем (накапливаем) баллы выстрелов.
for ii:= 1 to 20 do // чтобы двигалась оценка выстрела в Caption
begin delete(bus,1,1); // удаляю из строки bus 1-й символ
sleep(20); // пауза 20 миллисекунд (чтобы замедлить процесс)
Caption := bus + IntToStr(ball);
// в Caption помещаю эту стриженую строку пробелов,
// а справа цепляю оценку выстрела. (длина строки меняется)
end;
if count = 10 then // т е конец игры
begin
Caption := ' ' + IntToStr(suma) + ' очков (10 выстрелов)';
Timer1.Enabled := false; // отключаю работу таймера.
end;
end;
end;
procedure TForm1.btnRepeatClick(Sender: TObject);
begin // нажатие кнопки "Снова"
count := 0; // сбрасываю счетчик
suma:=0; // сбрасываю счетчик суммы очков
Timer1.Enabled := true; // включаю таймер
Caption := 'Начало';
end;
procedure TForm1.FormResize(Sender: TObject);
begin // срабатывает при изменениии размеров формы
if ClientWidth < 610 then width:= 615; //ограничиваю размеры снизу.
if ClientHeight < 450 then height := 500;
xmax := ClientWidth - 280; // пересчитываю xmax ymax
ymax := ClientHeight - 320;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin // срабатывает при запуске приложения, когда создается форма.
Bm_fon := TBitMap.create; // создаю объект TBitMap для фона.
try // защита от ошибок при работе с файлами.
if fileexists ('.\parket2.bmp') then // если существует файл parket2.bmp
begin BM_fon.LoadFromFile('.\parket2.bmp'); // загружаю рисунок из файла.
Canvas.Brush.BitMap :=BM_fon; // эту картинку присваиваю холсту формы.
end
except
end;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin // при выходе из проекта освобождается память, выделенная
// объектам.
Canvas.Brush.Bitmap := nil;
BM_fon.Free;
BM.Free;
end;
procedure TForm1.FormPaint(Sender: TObject);
begin
Canvas.FillRect(ClientRect);
// рисую прямоугольник с фоном, причем в качестве фона
// ранее была установлена картинка с фоном.
end;
end.