Постановка задачи
По всему экрану мелькает форма, и цель игры — успеть щелкнуть мышью на появившемся окне. Для победы необходимо "попасть" по окну десять раз. Следует учитывать, что при каждом "попадании" скорость перемещения окна увеличивается.
Разработка формы
Создадим новый проект Delphi. Мелькающее РѕРєРЅРѕ Сѓ нас будет необычным: РѕРЅРѕ будет без заголовка Рё РЅРµ прямоугольным, Р° эллиптической формы. Рзмените свойства формы согласно табл. 8.1.
Таблица 8.1. Свойства формы игры "Успей щелкнуть"
Свойство | Значение | Пояснение |
BorderStyle | bsNone | Окно программы будет отображаться без границы и заголовка |
FormStyle | fsStayOnTop | Окно программы должно располагаться поверх всех остальных окон, поскольку игрок не всегда будет "попадать" по нашему окну, а значит своими "промахами" будет активизировать другие окна |
Color | clWindowText | Цвет формы — черный |
Height | 72 | Высота |
Width | 208 | РЁРёСЂРёРЅР° |
Разместите РЅР° форме компонент Label категории Standard. Рзмените его свойства согласно табл. 8.2.
Таблица 8.2. Свойства первого компонента Label
Свойство | Значение | Пояснение |
Caption | Попадания: | Надпись метки |
Font.Color | clLime | Цвет шрифта — светло-зеленый |
Font.Name | Courier New | Название шрифта |
Font.Size | 12 | Размер шрифта |
Font.Style | [fsBold] | Начертание шрифта — полужирное |
Left | 16 | Отступ слева |
Top | 16 | Отступ сверху |
Разместите на форме еще один компонент Label и измените его свойства согласно табл. 8.3.
Таблица 8.3. Свойства второго компонента Label
Свойство | Значение | Пояснение |
Name | popad | Новое имя компонента |
Caption | 0 | Надпись метки |
Font.Color | clRed | Цвет шрифта — красный |
Font.Name | Courier New | Название шрифта |
Font.Size | 16 | Размер шрифта |
Font.Style | [fsBold] | Начертание шрифта — полужирное |
Left | 120 | Отступ слева |
Top | 16 | Отступ сверху |
Разместите на форме третий компонент Label, который будет отображать предельное число "попаданий", и измените его свойства согласно табл. 8.4.
Таблица 8.4. Свойства третьего компонента Label
Свойство | Значение | Пояснение |
Caption | /10 | Надпись метки |
Font.Color | clRed | Цвет шрифта — красный |
Font.Name | Courier New | Название шрифта |
Font.Size | 16 | Размер шрифта |
Font.Style | [fsBold] | Начертание шрифта — полужирное |
Left | 144 | Отступ слева |
Top | 16 | Отступ сверху |
Напоследок разместите на форме компонент Timer категории System. Результат оформления формы должен соответствовать рис. 8.1.
Рис. 8.1. Форма для игры "Успей щелкнуть"
Разработка программного кода
Рзменение формы РѕРєРЅР° РЅР° эллиптическую реализуется РІ обработчике события OnCreate формы. Для этого необходимо объявить глобальную переменную forma типа HRGN, которая будет содержать размеры РѕРєРЅР°:
var
В Form1: TForm1;
В forma: HRGN;
В обработчик события OnCreate добавьте следующий код:
procedure TForm1.FormCreate(Sender: TObject)
begin
 Randomize; //включаем генератор случайных чисел
В forma:= CreateEllipticRgn(0, 0, Form1.Width, Form1.Height) ; //РІРёРґ РѕРєРЅР°
 //применяем новый вид окна
В SetWindowRgn(Handle, forma, True);
end;
Здесь мы задаем окно в виде эллипса и применяем новый вид окна.
Каждую секунду форма должна случайным образом менять СЃРІРѕРё координаты РІ пределах экрана. Рто будет реализовано РІ обработчике события Timer1.OnTimer:
procedure TForm1.Timer1Timer(Sender: TObject);
begin
 Form1.Top:= Random(Screen.Height) + 1 ; //случайная высота
 Form1.Left:= Random(Screen.Width) + 1; //случайная ширина
end;
Здесь мы определяем высоту и ширину экрана, выбираем случайные координаты, не выходящее за пределы экрана, и перемещаем в них окно программы.
Теперь выделите все компоненты и саму форму и создайте для них общий обработчик события OnMouseDown:
procedure TForm1.popadMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
 if StrToInt(popad.Caption) < 10 then begin //если попаданий меньше 10
 //Перемещаем окно в случайную позицию по вертикали
В В Form1.Top:= Random(Screen.Height) + 1;
В В //Рзменяем положение РїРѕ горизонтали
В В Form1.Left:= Random(Screen.Width) + 1;
 //Увеличиваем счетчик "попаданий" на единицу
В В popad.Caption:= IntToStr(StrToInt(popad.Caption) + 1);
  //Увеличиваем скорость перемещения окна на 100 мс
  Timer1.Interval:= Timer1.Interval – 100;
В end;
 if popad.Caption = '0' then begin //если игрок попал 10 раз
 Timer1.Enabled:= False; //останавливаем игру
  Form1.Position:= poDesktopCenter; //окно – в центр экрана
  //сообщаем о победе
 ShowMessage('Вы попали по окну 10 раз!');
В В if Application.MessageBox('РРіСЂР°', 'Рграть еще раз?', mb_yesno + mbtaskmodal + mb_iconQuestion) = idYes
  then {предлагаем сыграть еще раз}
В В begin
  popad.Caption:= '0'; //сброс результатов
  //Придаем окну эллиптическую форму
В В forma:= CreateEllipticRgn(0, 0, Form1.Width, Form1.Height);
В В SetWindowRgn(Handle, forma, True);
  //Устанавливаем начальную скорость перемещения окна
В В Timer1.Interval:= 1000;
  Timer1.Enabled:= True; //начинаем игру
В end
 else Halt; //выход из игры
В end;
end;
При каждом "попадании" выполняется проверка: было ли это "попадание" последним. Если да, то просто пополняем счетчик попаданий и увеличиваем скорость перемещения формы на 100 мс. Если игрок сделал последнее "попадание", то останавливаем игру, выводим окно в центр экрана и показываем сообщение о том, что игра успешно окончена. После этого отображаем окно с вопросом: следует ли начинать игру заново. Если пользователь отказывается играть, то просто выходим из программы. Если пользователь хочет сыграть сначала, то обнуляем все результаты и начинаем игру заново.
Окно программы в процессе игры представлено на рис. 8.2.
Р РёСЃ. 8.2. РРіСЂР° "Успей щелкнуть" РІ действии
Полный исходный код модуля
Полный исходный код программного модуля игры "Успей щелкнуть" представлен в листинге 8.1.
Листинг 8.1. Программный модуль игры "Успей щелкнуть"
unit Unit1;
interface
uses
В Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls;
type TForm1 = class(TForm)
В Label2: TLabel;
В popad: TLabel;
В Label3: TLabel;
В Timer1: TTimer;
В procedure FormCreate(Sender: TObject);
В procedure Timer1Timer(Sender: TObject);
В procedure popadMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
private
В { Private declarations }
public
В { Public declarations }
end;
var
В Form1: TForm1;
В forma: HRGN;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject)
begin
 Randomize;//включаем генератор случайных чисел
В forma:= CreateEllipticRgn(0, 0, Form1.Width, Form1.Height); //РІРёРґ РѕРєРЅР°
 //применяем новый вид окна
В SetWindowRgn(Handle, forma, True);
end;
procedure TForm1.Timer1Timer(Sender: TObject);
begin
 Form1.Top:= Random(Screen.Height) + 1; //случайная высота
 Form1.Left:= Random(Screen.Width) + 1; //случайная ширина
end;
procedure TForm1.popadMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
 if StrToInt(popad.Caption) < 10 then begin //если попаданий меньше 10
 //Перемещаем окно в случайную позицию по вертикали
В В Form1.Top:= Random(Screen.Height) + 1;
В В //Рзменяем положение РїРѕ горизонтали
В В Form1.Left:= Random(Screen.Width) + 1;
 //Увеличиваем счетчик "попаданий" на единицу
В В popad.Caption:= IntToStr(StrToInt(popad.Caption) + 1);
  //Увеличиваем скорость перемещения окна на 100 мс
  Timer1.Interval:= Timer1.Interval – 100;
В end;
 if popad.Caption = '0' then begin //если игрок попал 10 раз
 Timer1.Enabled:= False; //останавливаем игру
  Form1.Position:= poDesktopCenter; //окно – в центр экрана
  //сообщаем о победе
 ShowMessage('Вы попали по окну 10 раз!');
В В if Application.MessageBox('РРіСЂР°', 'Рграть еще раз?', mb_yesno + mbtaskmodal + mb_iconQuestion) = idYes
  then {предлагаем сыграть еще раз}
В В begin
  popad.Caption:= '0'; //сброс результатов
  //Придаем окну эллиптическую форму
В В forma:= CreateEllipticRgn(0, 0, Form1.Width, Form1.Height);
В В SetWindowRgn(Handle, forma, True);
  //Устанавливаем начальную скорость перемещения окна
В В Timer1.Interval:= 1000;
  Timer1.Enabled:= True; //начинаем игру
В end
 else Halt; //выход из игры
В end;
end;
end.
⊚ Р’СЃРµ файлы проекта Рё исполняемый файл рассмотренной программы находятся РЅР° прилагаемом Рє РєРЅРёРіРµ компакт-РґРёСЃРєРµ РІ папке Chapter_08.