Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

ПП_Лаб1

.pdf
Скачиваний:
19
Добавлен:
11.02.2015
Размер:
528.52 Кб
Скачать

перемещение шарика в зависимости от его скорости и направления движения.

Кроме того, раз мы оперируем скоростью, связанной с временем, то нужно реализовать алгоритм засекания временных промежутков между перерисовками, чтобы быстродействие системы не влияло на работу алгоритма. В этом может помочь функция GetTickCount, которая возвращает число миллисекунд, прошедшее с момента запуска системы. Пусть в команду Move будет передаваться текущее значение счетчика, а внутри класса будет запоминаться предыдущее показание счетчика (разница предыдущего и текущего значения даст время в мс между двумя перерисовками).

С учетом вышесказанного описание класса будет выглядеть так:

Реализация функций класса будет выглядеть так:

Внесем изменения в основной код. Прежде всего изменим определение глобальной переменной типа CBall так, чтобы в нее передавались необходимые параметры:

Далее необходимо переработать цикл обработки сообщений таким образом, чтобы в случае отсутствия сообщений можно было использовать процессорное время для реализации физики системы. В этом поможет замена функции GetMessage на функцию PeekMessage. Разница между этими функциями в том, что, если GetMessage ожидает наступления сообщения, то PeekMessage даже в случае отсутствия сообщений немедленно возвращает управление. Измените цикл обработки таким образом:

Функция OnIdle будет вызываться тогда, когда сообщений в очереди нет. Реализуем OnIdle:

InvalidateRect говорит системе, что указанное окно содержит неверную графическую информацию, в ответ на этот вызов система посылает приложению WM_PAINT.

Запуск приложения позволяет увидеть движение шарика, однако есть побочный эффект – мерцание из-за того, что экран постоянно очищается и перерисовывается.

Убрать эффект мерцания можно, если делать отрисовку сцены в памяти, а потом целиком копировать в окно. Однако в нашем случае (простые объекты, простое управление объектами) можно просто ограничить частоту перерисовок. Частота обновления ~50 кадров в секунду будет приемлемой для человеческого глаза. При помощи команды Sleep добавим паузу перед обновлением экрана размером в 20 мс. Мерцание заметно, но уже не настолько:

Далее необходимо подобрать размер шарика и его скорость так, чтобы движение выглядело достаточно динамичным.

Следующим шагом будет реализация отталкивания шарика от стенок окна. Вся реализация алгоритма будет находиться в методе Move класса CBall. Для работы не хватает информации о границах окна. Добавим в класс поле типа RECT, которое будет описывать прямоугольник границ окна. Также добавим метод, устанавливающий границы.

Реализуем метод SetBounds:

Модифицируем метод Move так, чтобы границы окна учитывались при движении:

Дополнительная проверка на знак скорости нужна для того, чтобы избежать залипания шарика, если вдруг он по какой-то причине перейдет границу экрана.

Модифицируем основную программу, чтобы при старте шару передавались текущие границы окна:

Остался один нерешенный момент. Пользователь может изменить размеры окна. При этом необходимо передать новые границы окна шарику.

При изменении размеров окна система отправляет сообщение WM_SIZE. Сделаем обработку этого сообщения:

Здесь создается объект типа RECT, куда записываются значение ширины и высоты окна. Данные значения берутся из параметра lParam сообщения

WM_SIZE.

Добавление дополнительных препятствий

Реализуем дополнительные препятствия. Для простоты препятствие может быть только горизонтальным и будет иметь ширину 1 пиксел.

В отдельном файле CHLimiter.h опишем класс препятствия:

Препятствие характеризуется параметром y – высота расположения и параметрами xmin, xmax – размер и положение по горизонтали. Не забудьте добавить включение файла windows.h.

В файле CHLimiter.cpp реализуем кламм CHLimiter:

Метод MoveToEx перемещает позицию рисования, а метод LineTo – отрисовывает линию с текущей позиции до указанной.

Для добавления границы в программу внесем доработки в основной код программы.

1. Создание объекта:

2. Добавление объекта в отрисовку:

В результате граница появилась на экране, однако пока никакой реакции шарика на эту границу нет.

Добавим в класс шарика параметр – указатель на объект границы и метод передачи границы:

Не забудьте добавить заголовочный файл CHLimiter.h. Реализация метода SetHLimiter:

Модифицируем код приложения, чтобы при инициализации шарика к нему добавлялась информация о границе:

Шарик по-прежнему не реагирует на границу. Для получения реакции нужно модифицировать метод Move класса CBall:

Методику расчета координат шарика и сравнение их с координатами препятствия предлагается изучить и понять самостоятельно.

Движение препятствия в качестве реакции на действия пользователя

Модифицируем код таким образом, чтобы пользователь мог управлять положением препятствия при помощи клавиатуры.

Первым делом добавим методы MoveX и MoveY для препятствия:

Реализуем их:

Параметр inc показывает величину изменения положения.

Для обработки нажатий клавиш система передает приложению набор сообщений, одно из которых (WM_KEYDOWN) мы можем использовать для реализации движения.

Данное сообщение посылается при нажатии клавиши на клавиатуре. В случае, если клавиша не отпущена – сообщение генерируется с определенной периодичностью.

Добавим его обработчик и генерацию реакции на нажатие клавиш для препятствия:

Запустите приложение и попробуйте поуправлять препятствием при помощи клавиш управления курсором.

Следует заметить, что одновременное нажатие клавиш не обрабатывается, а также программа некорректно работает в случае наезда препятствием на шарик. Однако решение этих проблем представляет достаточную сложность, выходящую за рамки работы.

Подготовка отчета

Отчет к лабораторной работе должен включать:

1.Титульный лист.

2.Описание лабораторной работы.

3.Объяснение расчетов ограничений в методе CBall::Move.

4.Реализация индивидуального задания.

Индивидуальные задания

1.Реализуйте в классе CBall возможность задавать цвет шарика и модифицируйте приложение так, чтобы летало 2 шарика разных цветов и размеров.

2.Реализуйте возможность добавлять 2 горизонтальных препятствия, одно из которых подвижно.

3.Реализуйте возможность добавления вертикального подвижного препятствия. Модифицируйте приложение, чтобы было 1 подвижное вертикальное препятствие и неподвижное горизонтальное.

4.Модифицируйте класс CBall так, чтобы можно было управлять скоростью шарика. В обработчике клавиатурных сообщений добавьте реакцию на клавиши A и Q, уменьшающих и увеличивающих скорость шарика, соответственно.

5.Реализуйте препятствия в виде прямоугольников, имеющих толщину. Шарик может отражаться как от горизонтальных, так и от вертикальных граней.

6.Модифицируйте класс CBall и программу так, чтобы по нажатию клавиш можно было менять цвета летающих шариков. Шариков должно быть не менее 2.

7.Модифицируйте класс препятствия так, чтобы была возможность задавать и менять с клавиатуры цвет препятствия.

8.Модифицируйте классы и приложение так, чтобы при столкновении шарика с препятствием менялись цвета шарика и препятствия.