
Занятие 3 События от мыши
Когда по щелчку мыши должно выполняться какое-либо действие (рисование элемента, например) необходимо описать событие – что именно происходит с мышью (щелчок, двойной щелчок, перемещение). Задав событие, мы сможем открыть его обработчик.
Какие бывают события от мыши, прочитайте на стр. 129 в учебнике.
Для того чтобы задать событие, в Инспекторе объектов откройте вкладку Events (События). Чтобы задать событие «Нажатие кнопки мыши», выберите строку OnMouseDown, щелкните два раза по пустому окошку рядом с ней и вы получите в коде программы процедуру (но еще пустую, без операторов).
procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
end;
Это заготовка для обработки события OnMouseDown.
В этой процедуре напишите код, по которому на форме рисуется небольшой квадратик или кружочек, в том месте, где произошло нажатие.
Задача 1.
Проект «Попади в мишень»
Постановка задачи. В случайном месте формы рисуется небольшой кружок заданного радиуса и произвольного цвета. Одновременно запускается таймер, и играющий должен успеть щелкнуть по кружку. Число попаданий и число щелчков подсчитываются. Игра продолжается до 10 щелчков.
Реализация. Положите на форму таймер, установите подходящий интервал. Положите одну кнопку «Старт». Кнопка сначала видна, по ее нажатию обнуляются счетчики, и запускается таймер, а также свойству Button1.Visible присваивается значение false. Во время игры кнопка уже не видна. После 10 выстрелов форма очищается, и кнопка вновь видна. Число попаданий и выстрелов будем выводить в строке Form1.Caption (рис. 17).
Рис. 17. Форма проекта «Попади в мишень»
Потребуется написать процедуру mishen рисования кружка заданного цвета с использованием стандартного метода Ellipse. Если задать в параметрах процедуры Ellipse координаты квадрата, то будет рисоваться круг, а не эллипс. Используем следующие глобальные переменные
var cw,ch,rad, a,b:integer; // a, b – координаты левого верхнего угла мишени
vist, popal:integer;
c:TColor;
procedure mishen(x, y, rad : integer; c : TColor);
begin
with Form1.Canvas do
begin
Pen.Color:=c;
Brush.Color:=c;
Ellipse(x,y,x+2*rad,y+2*rad);
end;
end;
Ниже приведен код FormCreate, Timer1Timer, FormMouseDown и Button1Click.
procedure TForm1.FormCreate(Sender: TObject);
begin
randomize;
cw:=ClientWidth; // Ширина формы
ch:=ClientHeight; // Высота формы
rad:=10;
Timer1.Enabled:=false;
end;
procedure TForm1.Timer1Timer(Sender: TObject);
begin
c:=Form1.Color; // Закрашиваем мишень цветом формы
mishen(a,b,rad,c);
c:=RGB(random(256),random(256),random(256)); // Задаем случайный цвет
a:=1+random(cw-2*rad);
b:=1+random(ch-2*rad);
mishen(a,b,rad,c); // Рисуем мишень в новом месте
end;
procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var x1,y1:integer;
begin
vist:=vist+1;
{Переменные х, у – «экранные» координаты точки чувствительности мыши, поэтому пересчитаем их так, чтобы значения х1, у1 «были» внутри мишени, т.е. внутри }
x1:=abs(x-a)-rad div 2;
y1:=abs(y-b)-rad div 2;
if (x1*x1+y1*y1<=rad*rad) then
// Указатель мыши внутри мишени
begin
popal:=popal+1;
end;
Form1.Caption:='Выстрелов: '+IntToStr(vist)+
' Попаданий: '+IntToStr(popal);
if vist = 10 then
Begin
Timer1.Enabled:=false;
with Canvas do
begin
Font.Size:=24;
Font.Color:=ClTeal;
Brush.Color:=Form1.Color;
TextOut(70,80,'Игра окончена');
end;
Button1.Visible:=true; // Можем начать сначала
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
vist:=0;
popal:=0;
// Очистим форму
with Canvas do
begin
Pen.Color:=Form1.Color;
Brush.Color:=Form1.Color;
Rectangle(0,0,cw,ch);
end;
Timer1.Enabled:=true;
Button1.Visible:=false; // Кнопка невидима
end;
Задача 2
Проект «Снежинки»
Постановка задачи. Рисование снежинки на поверхности формы в точке, в которой пользователь нажал кнопку мыши. Демонстрирует использование процедуры PolyLine, а также процедуры обработки события OnMouseDown для получения координаты точки, в которой нажата кнопка мыши. При нажатии левой кнопки мыши цвет снежинки синий, а при нажатии правой – голубой (рис. 19).
Рис. 19. Результат работы программы «Снежинки»
Реализация. Напишем процедуру snowflake рисования снежинки. Входными параметрами для нее являются координаты x0, y0 центра снежинки и r − радиус снежинки.
procedure snowflake(x0,y0,r: integer);
// x0,y0 - координаты центра снежинки
// r - радиус снежинки
var p : array[1..21] of TPoint; // Массив координат лучей и впадин
a: integer; // Угол в градусах между осью ОХ и прямой, // соединяющей центр снежинки и конец луча или впадины
i: integer;
begin
a := 18; // Строим от правого горизонтального луча
for i:=1 to 20 do
begin
if (i mod 2 = 0) then
begin // Впадина
p[i].x := x0+Round(r/6*cos(a*2*pi/360));
p[i].y:=y0-Round(r/6*sin(a*2*pi/360));
end
else
begin // Луч
p[i].x:=x0+Round(r*cos(a*2*pi/360));
p[i].y:=y0-Round(r*sin(a*2*pi/360));
end;
a := a+18;
end;
p[21].x := p[1].x; // Замкнуть контур снежинки
p[21].y := p[1].y;
Form1.Canvas.Polyline(p); // Начертить снежинку
end;
На событие OnMouseDown напишем код, в котором проверяем, какая кнопка была нажата.
procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
if Button = mbLeft then // Нажата левая кнопка мыши
// Рисуем снежинку синим цветом
Form1.Canvas.Pen.Color := clBlue
else
Form1.Canvas.Pen.Color := clSkyBlue; // Рисуем снежинку голубым цветом
// Вызов процедуры отрисовки снежинки
snowflake(x, y, 10);
end;
Задание 3
Игра «Крестики - нолики»
При реализации этой игры надо помнить, что поле не обязательно должно быть размера 3 х 3. Размер может быть любым.
Напишите свою процедуру DrawPole, которая рисует поле, состоящее из N х N квадратиков, как указано на рисунке. Для этого задайте константу N и числа dx и dy, задающие сторону квадратика в пикселях. Задайте также местоположение сетки на форме, то есть координаты левого верхнего угла поля x0 и y0.
Н
а
рисунке (N = 5) выделен
квадратик с номером строки i
= 4 и номером столбца k
= 3. Для нахождения координат этого
квадратика на форме используем формулы
(1):
x = x0 + (k –1) * dx;
y = y0 + (i– 1) * dy.
Обратно, зная x и y, можно найти номер строки и номер столбца по формулам (2):
k = (x-x0) div dx+1;
i = (y-y0) div dy+1.
2. Положите на форму одну метку для вывода надписи: «Ходят крестики» или «Ходят нолики» и две кнопки: Start и Close. (Обычно первыми ходят крестики.)
3. Опишите глобальную переменную булевского типа, означающую признак того, что ходят крестики, например: var pr_krest:boolean.
4. Опишите тип массив размерностью N × N с элементами целого типа. Массив нужен для анализа того, кто победил: крестики или нолики. Процедурой mas_clear обнулите все элементы массива (см. ниже).
5. Изучите на стр. 129 события от мыши. Мышью будем указывать клетку, в которую будем выводить «Х» или «О» в зависимости от значения признака pr_krest. Эти буквы будем выводить с помощью метода TextOut. При этом мышь должна указать место на сетке, т.е. какой-либо квадратик с номером строки i и номером столбца k. В параметрах процедуры TForm1.FormMouseDown, являющейся обработчиком события «щелчок по левой кнопке», есть переменные x и y, возвращающие координаты мыши. Воспользуемся формулами (2)
k:=(x-x0) div dx+1;
i:=(y-y0) div dy+1;
с помощью которых мы узнаем номер строки и номер столбца квадратика [i,k]. Также мы занесем в соответствующую ячейку массива tab[i,k]:=1 (крестики) или 2 (нолики). Надо не забыть, что ставить крестик или нолик мы можем только в том случае, если в соответствующей ячейке массива стоит 0.
6. После того как крестик или нолик поставлен, надо организовать проверку по горизонтали, вертикали и диагонали. В случае успеха вывести соответствующее сообщение (например, «Выиграли крестики!»).
7. Игра заканчивается, если выигрыш или не осталось свободных клеток.