
Лабник по СПО
.pdfТекст программы на языке С++
Написание текста программы начинаем с объявления глобальных переменных в заголовочном файле:
Cardinal TT2,TTS, msTick; TDateTime BegTime; unsigned char Reg,StSt;
Переменная TT2 предназначена для хранения значения переменной TickCount при измерении фактического значения интервала таймера, переменная TTS предназначена для хранения значения переменной TickCount при работе секундомера. В переменной msTick предполагается хранить предыдущее значение секундомера. В переменной BegTime будем запоминать начальное время отсчёта, в переменных Reg и StSt - состояния кнопок RegButt
иStartBut.
Вобработчик события OnClick кнопки ButWatch вводим тексты операторов для задания положения формы относительно других форм. Проверяем правильность действия кнопки.
void __fastcall TfmTimer::ButWatchClick (TObject *Sender)
{
if (fmTimer->FormStyle==fsStayOnTop)
{
fmTimer->FormStyle=fsNormal; ButWatch->Caption="Назад";
}
else
{
fmTimer->FormStyle=fsStayOnTop; ButWatch->Caption="Поверх всех";
}
}
Вобработчик события OnTimer первого таймера вводим операторы для определения значения и вывода системного времени. Для сравнения форматов данных функции TimeToStr(Time) и функции DecodeTime(Time,h,m,s,ms) выводим системное время, возвращаемое функцией TimeToStr(Time), на заголовок формы, а время, возвращаемое функцией DecodeTime(Time,h,m,s,ms), выводим на метку WatchLb.
181
PDF created with pdfFactory Pro trial version www.pdffactory.com
void __fastcall TfmTimer::Timer1Timer(TObject *Sender)
{
Word h,m,s,ms; DecodeTime(Time(),h,m,s,ms);
WatchLb->Caption=IntToStr(h)+" час "+IntToStr(m)+ " мин " +IntToStr(s)+" с "+IntToStr(ms)+ " мс"; Caption = " Системное время-> "+TimeToStr(Time());
}
В обработчик события OnTimer второго таймера вводим операторы для вычисления фактического значения интервала таймера.
void __fastcall TfmTimer::Timer2Timer(TObject *Sender) {Word m,s,ms;
if (Timer2->Tag==0) TT2 = GetTickCount(); LabTickCount->Caption=IntToStr(GetTickCount()); if (Timer2->Tag==10)
{
Timer2->Enabled = false;
ms = (GetTickCount()-TT2)/10; m = ms/60000;
ms = ms-60000*m; s = ms/1000;
ms = ms-1000*s;
ValGet->Text=" "+IntToStr(s)+" с "+IntToStr(ms)+" мс";
}
Timer2->Tag=Timer2->Tag+1;
}
Операторы, изменяющие значение задаваемого интервала, вводим в обработчик OnChange редактора ValSet.
void __fastcall TfmTimer::ValSetChange (TObject *Sender)
{
Timer2->Interval = StrToInt(ValSet->Text ); Timer2->Tag = 0;
Timer2->Enabled = true;
}
182
PDF created with pdfFactory Pro trial version www.pdffactory.com
Вводом разных заданий для интервалов второго таймера попытаемся определить дискретность задания интервала.
Пуск и останов секундомера производим одной кнопкой. Для этого используем операторы, определяющие состояние кнопки Старт/Стоп по значению переменной StSt. void __fastcall TfmTimer::StartButClick
(TObject *Sender)
{
if (StSt == 0)
{
StartBut->Caption = "Стоп"; StSt = 1;
Timer3->Enabled = true; TTS = GetTickCount();
if (Reg==1) TTS = TTS - msTick; BegTime = Time();
}
else
{
StartBut->Caption = "Старт"; StSt = 0;
Timer3->Enabled = false;
}
}
Операторы для отсчёта времени между подачами команд Старт и Стоп запишем в обработчик события OnTimer третьего таймера. Подсчёт времени выполним двумя способами с выводом результатов на две метки - TickLab и TimeLab.
void __fastcall TfmTimer::Timer3Timer(TObject *Sender)
{
Word h,m,s,ms; Cardinal mT,sT,msT;
msT = GetTickCount()-TTS; msTick = msT;
mT = msT/60000; msT = msT-60000*mT; sT = msT/1000;
183
PDF created with pdfFactory Pro trial version www.pdffactory.com
msT = msT-1000*sT;
TickLab->Caption = " "+IntToStr(mT)+" мин "+ IntToStr(sT)+" с "+IntToStr(msT)+" мс"; DecodeTime(Time()-BegTime,h,m,s,ms); TimeLab->Caption=" "+IntToStr(m)+" мин " + IntToStr(s)+" с "+IntToStr(ms)+ " мс";
}
Изменение режима секундомера производим операторами, записанными в обработчик события кнопки.
void __fastcall TfmTimer::RegButtClick (TObject *Sender)
{
if (Reg==0)
{
RegButt->Caption = "Накопление"; Reg = 1;
}
else
{
RegButt->Caption = "Обнуление"; Reg = 0;
}
}
Имена дней недели записываем в массив Days при создании формы и в эту же функцию записываем оператор для определения даты и дня недели. В системе С++Builder дату необходимо определять отдельно, до определения дня недели.
void __fastcall TfmTimer::FormCreate(TObject *Sender)
{
AnsiString days[11] =
{"Воскресенье", "Понедельник", "Вторник", "Среда", "Четверг", "Пятница", "Суббота" }; TDateTime dtDate = DateToStr(Date()); DataLab->Caption = days[dtDate.DayOfWeek() - 1]+ ", "+dtDate+'.';
}
184
PDF created with pdfFactory Pro trial version www.pdffactory.com
Оператор DayOfWeek(Date) возвращает день недели целым числом от 1 до 7, считая первым днём недели воскресенье. Нумерация элементов массива в языке С++ всегда начинается с нуля, поэтому номер дня недели на единицу меньше числа, полученного от функции.
Контрольные вопросы
1.Как определить системное время?
2.Как неактивное окно разместить поверх активного окна?
3.Как определить временной интервал?
4.Как влияет на погрешность показаний часов длительность интервала таймера, управляющего работой часов?
5.Через сколько времени обнуляется переменная TickCount?
6.Чему равно значение переменной TickCount?
7.Что необходимо предусмотреть для запуска и останова секундомера одной кнопкой?
8.Скажите, как при наличии нескольких таймеров на форме влияет изменение значения свойства Tag в одном таймере на значения этого же свойства других таймеров?
185
PDF created with pdfFactory Pro trial version www.pdffactory.com
Лабораторная работа № 8. Мультипликация
Задание
Цель работы:
1.Изучение методов создания изменяющихся графических изображений с элементами мультипликации.
2.Освоение методов создания непрерывного управляемого потока с помощью таймера.
Содержание работы:
Разработка приложения, демонстрирующего непрерывное движение одного объекта на фоне другого объекта.
Технические требования к приложению:
Отображаемые рисунки: облака и самолёт на фоне облаков. Регулируемый параметр - скорость движения.
Виды команд: старт, стоп, задание скорости полёта. Режимы движения:
Ÿс заданной скоростью на высоте, выбираемой случайно;
Ÿс уменьшением высоты после подачи команды Стоп или задания скорости равной нулю;
Ÿс увеличением высоты, до окончания набора высоты, после подачи команды начала движения.
Форма отчёта:
Текст проекта в папке с именем Work8 на диске Н:.
Содержание отчёта:
Файлы проекта и исполняемый файл.
186
PDF created with pdfFactory Pro trial version www.pdffactory.com
Способы создания движения
Под мультипликацией подразумевается создание движущегося и меняющегося рисунка. В некоторых случаях можно ограничиться только движением или только изменением содержания рисунка. Обеспечить движение рисунка или его части просто: сначала надо вывести рисунок на экран, затем стереть его и вновь вывести на новом месте. Подбором интервала времени между моментами вывода рисунка и расстояния
между старым и новым положениями рисунка можно изменять скорость перемещения рисунка. Для того чтобы движение было плавным и непрерывным, частота вывода изображения должна быть более 16 Гц, т.е. временной интервал между выводом двух изображений не должен превышать 62,5 мс. При формировании изображения
непосредственно на экране и полной перерисовке картинки обычно возникает заметное мерцание изображения и трудно обеспечить плавное непрерывное движение.
Одним из возможных способов решения проблемы может быть использование метода двойной буферизации. Для реализации метода в памяти создаётся битовая матрица, используемая в качестве промежуточного буфера. Изображение создаётся в битовой матрице и по завершении каждого кадра копируется в отображаемый буфер. Иными словами, программа работает с двумя плоскостями: одна плоскость отображается на экране, другая - используется для рисования. Когда рисунок завершён, два буфера меняются местами, вследствие чего становится видимой ранее скрытая плоскость. Функция CopyRect позволяет быстро копировать созданное изображение в отображаемый рисунок. Инструкция применения метода CopyRect выглядит так:
Canvas1->CopyRect(Область1, Canvas2, Область2);
где Canvas1 - поверхность, на которую выполняется копирование; CopyRect - метод объекта Canvas1; Canvas2 - поверхность, с которой выполняется копирование; Область1 - структура типа ТRect, задающая положение и размеры области поверхности Canvas1, в которую вставляется копируемое изображение; Область2 - структура типа ТRect, задающая положение и размеры области поверхности Canvas2, из которой происходит копирование.
Если размеры областей не совпадают, то происходит изменение масштаба изображения.
Схема приложения
Схема программы (рис.8.1) представляет собой непрерывный цикл, в котором пересчитываются координаты самолёта, выводится его изображение и восстанавливается
187
PDF created with pdfFactory Pro trial version www.pdffactory.com

испорченное изображение фона. Организацию непрерывного цикла, обеспечивающего изменение координат, удаление и вывод изображения самолёта выполним с помощью таймера.
1
Начало
|
|
2 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4 |
|
|
|
? |
|
|
|
Да |
|
|
|
|
|
|
|
|
|
|
|
||||||
|
|
Создание |
|
|
|
|
|
|
|
|
|
|
|
Выход |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||||||||||||||||||
граф. объектов |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||||||||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||||||||||||||
|
|
|
|
|
|
|
|
|
Нет |
|
|
|
5 |
|
|
|
|
|
|
|
|
|
|
|||||||||||||||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||||||||
|
3 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Конец |
|
|
|
||||||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||||||
|
Задание нач. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||||||||||||
|
|
|
6 |
|
|
|
? |
|
|
|
Да |
|
|
|
|
|
|
|
|
|
|
|
||||||||||||||||||||||||||||
|
|
координат |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||||||||||||||||
|
|
|
|
|
|
|
Изм. скорость |
|
|
|
|
|
|
|
|
|
|
|
||||||||||||||||||||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Нет |
|
|
|
|
|
|
|
|
|
|
|
7 |
|
|
|
|
|
||||||||
|
|
|
|
|
|
|
|
|
22 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Задание dx |
|
||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||||||||||
Отображение |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||||||||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||||||||||
|
|
|
|
|
|
|
|
|
|
фона |
|
|
|
|
|
8 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
х := х+ dx |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||||||||
|
21 |
|
. изобр. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||||||||||
|
|
|
|
|
|
Удал |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||||||||
|
|
|
|
самолёта |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
? |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||||
|
|
20 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Режим |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||||||||||||||||||||||
|
|
|
Задержка 25 мс |
|
|
|
|
|
|
|
движения |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||||||||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||||
19 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||||||
|
|
|
|
|
Рисование |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"Старт" |
|
|
|
||||||||||||||||||
|
|
|
|
|
самолёта |
|
|
"Гор" |
|
|
|
|
|
|
|
|
|
|
"Стоп" |
|
|
|
|
|
|
|
|
|||||||||||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
15 |
? |
|
|
|
|
|
Нет |
||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||||||
18 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||||||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12 |
|
|
|
|
|
|
|
|
|
|
|
|
|
dx = 0 |
|
|
|
|
|
|||||||||
|
|
|
|
|
|
|
|
Копирование |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||||||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
фона |
|
|
|
|
|
|
dx := 0 |
|
|
|
Да |
|
|
|
|
|
|
|
|
|
|
|
|||||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
16 |
|
? |
|
||||||||||||||||||||||||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
10 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
? |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Нет |
|
Взлёт |
|||||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Нет Граница |
|
|
|
? |
|
|
|
|
|
|
|
|
|
|
||||||||||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
|
|
|
|
|
|
|
|
|
|
Да |
||||||||||||||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Да |
|
|
|
|
|
|
|
Высота>0 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Нет |
|
|
|
|
|
|
17 |
|
|
|
||||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Да |
|
|
|
|
|
|
|
y := y–1 |
||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
y |
:= |
|
Random |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
14 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||||||||||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
y+1 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
y := |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Рис.8.1. Схема программы, демонстрирующей полёт самолёта
Работа программы должна начинаться с создания графических объектов и определения их начальных координат. Затем должна производиться проверка команд на закрытие программы, задание скорости, на начало или прекращение движения. Режимы движения могут быть трёх видов: равномерное горизонтальное движение на постоянной высоте (режим Гор), посадка после подачи команды Стоп или уменьшения скорости до нуля и взлёт после команды Старт, если самолёт был перед этим посажен и если заданное значение скорости больше нуля. После проверки наличия всех команд и выбора режима должен производиться вывод изображения самолёта, выдержка заданного времени, удаление изображения самолёта, восстановление фона, а затем повторение всех действий. Фактически вся программа является одним непрерывным циклом. Цикл не
188
PDF created with pdfFactory Pro trial version www.pdffactory.com

останавливается даже в режиме Стоп. В режиме Стоп цикл продолжает работать, но рисует самолёт на одном и том же месте.
Создание проекта
Создаём проект типа VCL Forms Application. Сохраняем проект в подготовленной заранее папке с именем Work8, присваиваем главному модулю имя UnPlane, а проекту - имя Plane. Присваиваем главной форме имя fmPlane.
Размещаем на форме визуальные объекты в соответствии с рис.8.2.
Рис.8.2. Главная форма проекта
Поместим на форму панель для объединения объектов управления. Свойству Align панели присвоим значение alBottom. На панели установим полосу прокрутки ScrollBar1 для регулирования скорости полёта, установим кнопку StrStop для подачи команд Старт и Стоп, и кнопку ClseBtn - для закрытия программы.
Поместим на форму объект типа TImage. Свойству Align объекта Image1 присвоим значение alClient. Свойствам akLeft, akTop, akRight и akBottom объекта Image1 присвоим значение True. Это необходимо, для того чтобы размеры рисунка отслеживали изменения размеров формы. В свойство Picture объекта Image1 введём рисунок облаков из файла sky.bmp. Для того чтобы рисунок занимал весь объект, свойству Stretch присвоим значение True.
Установим на форму объект Timer. Зададим свойству Interval таймера значение
1 мс.
189
PDF created with pdfFactory Pro trial version www.pdffactory.com

В данном примере использован файл plane.bmp с изображением самолета, перемещающегося на фоне облаков. Увеличенное изображение самолёта, разделенное на точки, приведено на рис.8.3.
Рис.8.3. Изображение самолёта
Первый рисунок используем в качестве неподвижного фона, второй рисунок, меньшего размера, перемещаем на фоне первого рисунка. Для ускорения процесса перерисовки, стирать и восстанавливать будем только ту часть фона, которая была закрыта перемещающимся объектом.
Вывод рисунка на поверхность формы производится методом Draw. В качестве параметров методу передаются координаты x,y левого верхнего угла прямоугольника, на которой будет выведен битовый образ. Если перед применением метода Draw свойству Transparent битового образа присвоить значение True, то элементы рисунка, цвет которых совпадает с цветом левой нижней точки рисунка, не будут выведены. Получим эффект прозрачного фона. Если прозрачными нужно сделать другие элементы, то необходимо указать цвет, который должен стать прозрачным, присвоив соответствующее значение свойству TransparentColor. В результате объединения рисунков получим изображение, показанное на рис.8.4.
Рис.8.4. Результат объединения рисунка облаков с рисунком самолёта
190
PDF created with pdfFactory Pro trial version www.pdffactory.com