Задание для расчётно-графической работы «Анимация нескольких объектов»
Задача.
Создать программу, которая выводит в окне движущиеся круги, обрабатывая при этом столкновения этих объектов с краями окна и между собой.
Программа должна работать следующим образом:
Чтение описания объектов из файла scene.txt
Анимации движения объектов с обработкой:
соударений с краями окна
соударений с другими объектами
соответствующих действий при соударении (см. варианты)
гравитации
вязкости
вращения (Дополнительно задание)
клика мыши (Дополнительно задание)
Обработка сохранения и восстановления состояния сцены в файл
Задача разбивается на следующие этапы реализации (подробности ниже):
Составление структуры, описывающей объект
Реализация чтения файлов с объектами
Вывод объектов на экран (без движения)
Реализация «простого» движения без соударений
Обработка соударения с краями окна
Обработка соударения с другими объектами
Обработка гравитации и вязкости
Добавление функции сохранения «сцены»
Анимация
Основной принцип анимации в данной работе похож на анимацию в мультфильмах: рисуем картинку, снимаем кадр, рисуем новую картинку, снимаем еще кадр… Его можно представить следующим образом:
Затираем старое изображение экрана фоновым цветом
Выводим предметы на экран
Пересчитываем координаты (и другие параметры) предметов
Снова с пункта 1
Если расписывать более детально, то в п.2 и п.3 необходимо пройтись по массиву объектов, и соответственно вывести их на экран или пересчитать их параметры.
Основную сложность данной работы будет представлять пункт 3, который и разбирается ниже.
Внимание! Если между пунктами 2 и 3 делать небольшую паузу, то анимация будет более плавной. Рекомендуется делать задержку в 0.1 сек (с помощью функции delay).
Движение объектов
Для простоты все объекты в данной работе представляют собой круги, с картинками внутри.
Для удобства пересчетов круг будем описывать следующими параметрами:
// описание шара
struct SBall
{
double x; // x координата центра круга
double y; // y координата центра круга
double radius; // радиус круга
double vx; // скорость круга по оси x
double vy; // скорость круга по оси y
int color1, color2; // основной и дополнительный цвета
};
x,y – текущие координаты центра круга. vx,vy – скорость круга. Новые координаты круга высчитываются по известной формуле . dt – это прошедший временной промежуток, шаг. Будем считать его постоянным и равным 0.1 сек. Таким образом мы получаем следующие формулы.
x = x + vx*dt;
y = y + vy*dt;
Для простейшего движения круга по экрану этого пересчета вполне достаточно.
Для того, чтобы заставить двигаться несколько подобных объектов, необходимо составить массив из них и в нужный момент обходить его и пересчитывать все координаты.
Соударение
Задача обработки соударений сводиться к следующему алгоритму:
Обходим все объекты, о которые можно «удариться».
Проверяем есть ли соударение.
Если есть – пересчитываем скорость объекта(-ов).
Пересчитываем координаты объекта.
Отражение от краев окна
Обработка соударения о края довольно проста. Имея координаты центра круга и радиус, для проверки наличия соударения достаточно простого сравнения. А для пересчета скорости необходимо просто поменять знак в соответствующей компоненте.
Рассмотрим в качестве примера обработку удара о нижнюю границу.
const int height = ?; // высота окна в пикселях
SBall B; // описание шара
// Проверка столкновения
if(B.x + B.radius >= height)
{
B.vx = -B.vx;
}
Предложенный алгоритм - упрощённый, при его применении у края экрана могут возникнуть «залипания», «туннельный эффект» и другие неправдоподобности. В рамках решаемой задачи этими эффектами можно пренебречь. Однако наиболее «продвинутые программисты», конечно, сумеют от этих эффектов избавиться!