Тема: Расчет траектории движения ⇐ ПредыдущаяСтр 5 из 5
Задание: Создание модели движения тел по определенной траектории. (http://programmersforum.ru/showthread.php?t=25052&highlight=%F1%EE%EB%ED%E5%F7%ED%E0%FF+%F1%E8%F1%F2%E5%EC%E0) Рассмотрим способы моделтрования движения простых тел на примере модели солнечной системы. 1) Параметры модели: · солнечная система представляет собой солнце и вращающиеся вокруг него 9 планет. Каждая из них имеет свою орбиту, свою скорость, массу и т.д. На заметку: планет всего 8, а 9-я - это астероид прилетевший с астероидного пояса ), но мы же не астрономы J. · размеры планет будут отрисовываться не в масштабе, но так, чтобы все планеты были различимы. · орбиты планет будут представлену упрочено – окружностями · параметры планет: http://www.astronet.ru/db/msg/eid/FK86/planets
2) Создайте проект File->New->VCL Forms Application C++ Builder · Свойствам формы в инспекторе объектов задайте значения: Left: 0 Top: 0 ClientWidth: 800 ClientHeight: 600 · На Tool Pallete во вкладке System выберите инструмент TTimer и перенесите его на форму. Задайте интервал таймера равным 20 мс. Interval=20 · Определяем параметры планет. Создадим структуру TPlanet с полями содержащими свойства планеты в файле Unit1.h Код: struct TPlanet { int x; int y;//это для удобства, координаты всегда будут "под рукой" int period; //период обращения вокруг солнца (в сутках) int orbit; //расстояние орбиты от солнца int angle; //текущее положение планеты на орбите byte radius; //радиус планеты TColor color; //цвет планеты string name; //имя планеты } В разделе public конструктора TForm1 объявим ссылки на переменные, понадобятся два битмапа, один для фона — cosmos, второй для буфера — buffer ( в буфере будет строиться изображение перед выводом его на экран). Еще нам понадобится массив планет — planets. Код (Unit1.h): public: // User declarations TPlanet *planets; Graphics::TBitmap *cosmos; Graphics::TBitmap *buffer;.
· Теперь создадим небо и звезды. Щелкните дважды по форме, среда создаст при этом обработчик создания формы FormCreate. Заполним его. Код: #include <stdlib.h> #include <stdio.h> #include <time.h>
void __fastcall TForm1::FormCreate(TObject *Sender) { randomize(); // инициализируем генератор случайных чисел. cosmos=new Graphics::TBitmap(); // это у нас фон buffer=new Graphics::TBitmap();// создаем буфер.
// Задаем ширину меньшую на 200, чем ширина формы, в правой части формы у нас будут несколько элементов управления, но это потом. cosmos->Width=ClientWidth-200; cosmos->Height=ClientHeight;
// Заливаем фон целиком черным цветом. cosmos->Canvas->Brush->Color=0; cosmos->Canvas->FillRect(cosmos->Canvas->ClipRect);
// это будут звезды for (int i=0; i<99; i++) cosmos->Canvas->Pixels[Random(ClientWidth-200)][Random(ClientHeight)]=clWhite;
// Вместо того, чтобы писать несколько строк кода, просто скопируем его функцией Assign. Она копирует не только изображение, но и все другие свойства битмапа, делает полную его копию. buffer->Assign(cosmos); }
· Осталось немного, и наш космос можно будет увидеть. В обработчике событий таймера вставляем процедуру рисования планет: void __fastcall TForm1::Timer1Timer(TObject *Sender) {DrawSystem(); } теперь напишите саму процедуру DrawSystem, в ней мы копируем фон (космос со звездами) в буфер. И второй строкой выводим буфер на канву формы, т.е. на экран. Спросите, зачем нужен буфер? Потом узнаете. · Код: void __fastcall TForm1::DrawSystem(TObject *Sender) { buffer->Canvas->Draw(0,0,cosmos); Canvas->Draw(0,0,buffer); } Теперь жмите F9. На форме должен появиться космос со звездами, и справа свободное место. · Космос мы уже создали. Теперь займемся планетами. Нам нужно позаполнять свойства у всех планет. Запишем их в константы. Код: TColor colors[9]={11713464, 2985931, 15571305, 1928136, 8304062, 5288427, 16178350, 13074777, 11713464}; byte radiuses[9]={3, 5, 6, 4, 12, 10, 8, 7, 2}; String names[9]= {"Меркурий", "Венера", "Земля", "Марс", "Юпитер", "Сатурн", "Нептун", "Уран", "Плутон"}; int orbits[9] = { 20, 35, 50, 70, 100, 145, 190, 240, 290}; //единственный реальный параметр int periods[9]={ 88, 225, 365, 687, 4332, 10762, 30689, 60201, 90485}; int SUN_RADIUS = 10; int CX = 300; //это координаты цетра нашей системы, вокруг него все и будет вращаться. int CY = 300; · Теперь напишем процедуру TForm1::InitPlanets() заполнения этих данных в массив, и добавим вызов процедуры InitPlanets() в FormCreate, в самый конец. Код (не забудьте объявить функцию!): void __fastcall TForm1::InitPlanets() {planets=new TPlanet[9]; for (int i=0; i<9;i++) { planets[i].radius=radiuses[i]; planets[i].name=names[i]; planets[i].color=colors[i]; planets[i].orbit=orbits[i]; planets[i].period=periods[i]; planets[i].angle=double(Random(628))/100.; } } · Пора поговорить про анимацию. У нас будет предельно простая, но все же анимация. Будет движение объектов, а именно планет, по окружности. Для начала рассмотрим принцип прямолинейного движения. При прямолинейном движении координаты объекта меняются обычным прибавлением или вычитанием. Например при горизонтальном движении Y координата остается неизменной, а X меняется с определенным шагом, если меняется в большую сторону, объект движется вправо, в меньшую – влево. Шаг изменения определяет скорость перемещения наравне с интервалом таймера, нужно подбирать их так, чтобы движение выглядело “мягче”. Перед тем как рассмотреть движение по окружности, нарисуем солнце и планеты, чтобы было понятно, что и куда мы будем двигать. Нарисуем просто – кружочки разного цвета, если хотите можете потом сделать более красиво. Теперь допишем процедуру DrawSystem, напомню, в ней происходит отрисовка. Первая и последняя строки вам знакомы, между ними теперь есть отрисовка солнца, и планет в цикле. Код: void __fastcall TForm1::DrawSystem() { buffer->Canvas->Draw(0,0,cosmos); buffer->Canvas->Brush->Color=clYellow; buffer->Canvas->Pen->Color=clYellow; buffer->Canvas->Ellipse(cX-SUN_RADIUS, cY-SUN_RADIUS, cX+SUN_RADIUS, cY+SUN_RADIUS); for(int i=0; i<9; i++) { planets[i].x=planets[i].orbit*cos(planets[i].angle)+cX; planets[i].y=planets[i].orbit*sin(planets[i].angle)+cY; buffer->Canvas->Brush->Color=planets[i].color; buffer->Canvas->Pen->Color=planets[i].color; buffer->Canvas->Ellipse(planets[i].x-planets[i].radius, planets[i].y - planets[i].radius, planets[i].x+planets[i].radius, planets[i].y + planets[i].radius); } Canvas->Draw(0,0,buffer); }; · Теперь приступаем к моделированию движения по окружности. Пусть земля в модели будет совершать один оборот за 1 секунду. void __fastcall TForm1::Move() {double dt=1e-3*M_PI*2*Timer1->Interval*planets[2].period; for(int i=0; i<9; i++) {planets[i].angle+=dt/planets[i].period; if(planets[i].angle>M_PI*2)planets[i].angle-=M_PI*2; planets[i].x=planets[i].orbit*cos(planets[i].angle)+cX; planets[i].y=planets[i].orbit*sin(planets[i].angle)+cY; } }; · Теперь допишем процедуру Move() в таймер void __fastcall TForm1::Timer1Timer(TObject *Sender) {Move();DrawSystem();} Результат ©2015 arhivinfo.ru Все права принадлежат авторам размещенных материалов.
|