Назад Оглавление Дальше Игра ТИР


В этом проекте мы изучаем обработчики событий и некоторые способы работы с графическими объектами. На форму ставится компонент 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;
В ней достаточно комментариев. Дополнительно отмечу следующее:
  1. Все же как хорошо, что координаты курсора в момент нажатия (относительно верхне-правого угла окна Image1) передаются в виде параметров X,Y и програмисту нужно заботиться только об их использовании.
  2. type TMouseButton = (mbLeft, mbRight, mbMiddle); здесь не используется, т е можно стрелять и правой мышкнопкой (можно попробовать). Если хотите только левую - добавьте в начало процедуры: if Button <> mbLeft then exit; Т е выход, если кнопка не левая.
  3. Координаты x=121, y=121 - это центр мишени. Ocki - это расстояние "пробоины" от центра мишени (согласно теореме Пифагора). Пересчет (т е отображение) очков в баллы подобрано так, чтобы в центре было 10 баллов, на крайнем кольце - 1 балл (приближенно).
  4. Чтобы подчеркнуть результат выстрела, балл(ball) выводится с движением. Для этого слева от него помещена строка bus из 20 пробелов. Балл выводится циклически (повторно) 20 раз (при помощи оператора for) и при каждом выводе процедура delete откусывает у строки bus 1-й символ, т е строка становится короче, в результате балл движется влево. Поясним, что caption - это заголовок формы (синяя полоса сверху). После последнего выстрела (count=10) выводится набранная сумма очков и отключатся таймер, т е прыжки мишени.
Полезно посмотреть описание этого обработчика OnMouseDown в предыдущей беседе.

Рисование фона формы выполено за счет:

  1. При создании формы (это еще раньше, чем срабатывает FormShow) срабатывает процедура FormCreate. Посмотрите, что в ней. В частности: создается объект Bm_fon - для работы с картинкой фона. Картинка загружается из файла parket2.bmp. Предварительно функция fileexists проверяет наличие этого файла в папке проекта. И наконец, картинка присваивается: Canvas.Brush.BitMap :=BM_fon; Свойство brush (кисть) - это как раз и есть фон. Можно задать его цвет (Brush.Color), а можно задать фоновую картинку, которая будет повторяться, если она меньше окна.
  2. Фактически же эта картинка будет нарисована процедурой FormPaint (смотри) при выполнении Canvas.FillRect(ClientRect); здесь: ClientRect - объяснено выше, FillRect - метод, закрашивающий прямоугольник той кистью (brush), которая есть в данный момент. А этой кисти мы только что пирсвоили нашу картинку. Так что вы можете заменить файл parket2.bmp и фон изменится.
  3. При выходе из проекта объекты, созданные с помощью create, нужно освободить (хороший - рекомендуемый стиль). Это делается в FormDestroy, т е при разрушении формы, т е при завершении работы проекта.

Текст этого модуля (Unit1.pas)

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.
игра delphi

Скачать RAR-архив исходников (11 Кб)
Скачать RAR-архив исходников + .exe(200 Кб)

Назад Дальше
Rambler's Top100
Hosted by uCoz