1. Пользуйтесь тегами кода. - [code] ... [/code] 2. Точно указывайте язык, название и версию компилятора (интерпретатора). 3. Название темы должно быть информативным. В описании темы указываем язык!!!
Ex - это расстояние по оси OX, которое соответствует изменению скорости частицы на 1. То есть, если DeltaX кометы от Солнца будет равно Ex или меньше, то начальная скорость частиц будет максимальной, если Ex .. 2*Ex - то скорость уменьшится на 1, и так далее... Этим и занимается функция Cvt. Ну, и добавляются небольшие рандомные отклонения, чтоб не было все как по линеечке. То же самое касается и Ey, только по оси OY...
Естественно, что скорость (как Vx так и Vy) частицы складывается с соответствующей скоростью кометы. То есть, всё по-взрослому А дальше уже частица летит сама по себе, испытывая на себе только незначительное влияние солнечного ветра, которое ослабляется с удалением от Солнца (см. метод Particle::Recalc())
, и аналогичный чуть ниже в Recalc...
Цитата
Только я теперь не знаю за что взяться, то ли продолжать свой код (выдрать у тебя только комету с хвостом) , то ли твой исходник переделывать
Ну, это уже тебе решать. Я только показал пример реализации. Справишься с написанием всей программы в подобном стиле - бери и дорабатывай мой каркас. Не справишься - продолжай свою программу.
Ex - это расстояние по оси OX, которое соответствует изменению скорости частицы на 1. То есть, если DeltaX кометы от Солнца будет равно Ex или меньше, то начальная скорость частиц будет максимальной, если Ex .. 2*Ex - то скорость уменьшится на 1, и так далее... Этим и занимается функция Cvt. Ну, и добавляются небольшие рандомные отклонения, чтоб не было все как по линеечке. То же самое касается и Ey, только по оси OY...
Естественно, что скорость (как Vx так и Vy) частицы складывается с соответствующей скоростью кометы. То есть, всё по-взрослому А дальше уже частица летит сама по себе, испытывая на себе только незначительное влияние солнечного ветра, которое ослабляется с удалением от Солнца (см. метод Particle::Recalc())
, и аналогичный чуть ниже в Recalc...
Ну, это уже тебе решать. Я только показал пример реализации. Справишься с написанием всей программы в подобном стиле - бери и дорабатывай мой каркас. Не справишься - продолжай свою программу.
Вряд ли справлюсь , за пример спасибо, покапаюсь конечно в нем))) Вот сегодня запустил несколько планет)))) Код конечно плохой, но уж строго не суди, не программист)
И у меня вопрос, можно ли как-нибудь мерцания избежать и перепрыжку рисовки планет через ось по Y ( Если взять центр координат середину экрана)
код:(Показать/Скрыть)
#include <iostream.h> #include <conio.h> #include <stdlib.h> #include <dos.h> #include <graphics.h> #include <math.h> class Star { protected: int xs,ys,rs,clrs; public: Star(int x,int y,int r, int clr): xs(x),ys(y),rs®,clrs(clr) {cout<<"Create Star\n";} void Show() {setcolor(clrs);circle(xs,ys,rs);} }; template <int orbp> class Planeta { protected: int rp,clrp,svrp,px,py; int dv; int xy[2][orbp*4]; public: Planeta(int r, int clr,int svr): rp®,clrp(clr),svrp(svr),dv(0) {/*cout<<"Create Planeta\n";*/} void Set(); void Show(int ipx,int ipy) {setcolor(clrp);circle(ipx,ipy,rp); //cout<<"x="<<x<<" y="<<y; } void Hide() { int prev_clrp = clrp; clrp=getbkcolor(); Show(xy[0][dv],xy[1][dv]); clrp = prev_clrp; } void Move(); } ; template <int orbp> void Planeta<orbp>::Set() {
int ix=getmaxx()/2+orbp; int iy=getmaxy()/2; xy[0][0]=ix; xy[1][0]=iy; xy[0][orbp*2]=getmaxx()/2-orbp; xy[1][orbp*2]=iy; for(int i=1,j=orbp*4-1;i<orbp*2;i++,j--) { ix--; iy=int(sqrt(abs(pow(orbp,2)-pow((ix-getmaxx()/2),2)))); xy[0][i]=ix; xy[1][i]=getmaxy()/2-iy; xy[0][j]=ix; xy[1][j]=getmaxy()-xy[1][i]; };
А ты понимаешь причину такой перепрыжки? Хочешь я добавлю к твоему коду 3 строки и ты сразу поймешь в чем дело? Смотри:
for(int dv = 0; dv <= 4 * orbp; dv++) { putpixel(xy[0][dv], xy[1][dv], LIGHTGRAY); }
Вот это добавь в самый конец Set(). Так сказать, чтобы очертить орбиту. И обрати внимание, с какой частотой у тебя точки стоят в одном месте, и насколько они редко расположены в другом (вот там где они реже всего и будет "перепрыжка". Но на самом то деле я бы это "перепрыжкой" не называл. Это то, как должно быть, именно там ведь у тебя и нет мерцания, правда? Мерцает в других местах траектории, потому что там обновление происходит слишком часто). Если б мне понадобилось запомнить координаты точек орбиты, я бы прошелся одним циклом от 0 до 359 градусов + sin и cos, и все точки были бы с одинаковой частотой. И тогда не будет вот этих "перепрыжек", и (скорее всего) уменьшится мерцание, ибо перерисовываться-то оно будет, но насколько реже - ты даже не представляешь Если же тебе надо не круговую, а эллиптическую орбиту... Ну что ж, уравнение эллипса тоже не является секретом, точки вычисляются ненамного сложнее чем орбита круговая.
Ууу... Как все запущено. Радианы и градусы - разные вещи, правда? Вот библиотека math подразумевает, что тригонометрические функции работают с радианами. Делаем проще:
// Не надо каждый градус, при таком маленьком радиусе достаточно каждого четвертого for(int i = 0; i < 360; i += 4) { putpixel( (getmaxx()/2 + 70*cos(i*M_PI/180)), (getmaxy()/2 + 70*sin(i*M_PI/180)), LIGHTGRAY ); delay(50); }
Ууу... Как все запущено. Радианы и градусы - разные вещи, правда? Вот библиотека math подразумевает, что тригонометрические функции работают с радианами. Делаем проще:
// Не надо каждый градус, при таком маленьком радиусе достаточно каждого четвертого for(int i = 0; i < 360; i += 4) { putpixel( (getmaxx()/2 + 70*cos(i*M_PI/180)), (getmaxy()/2 + 70*sin(i*M_PI/180)), LIGHTGRAY ); delay(50); }
Вопрос такой.. Тема вызывает интерес, и это понятно. Но BC у меня (и не только, думаю) нет. Можно ли и накормить волков (то есть преподавателей топикстартера), и сохранить овец (чтоб я и остальные могли компилировать прогу)? Я, конечно, могу переделать всю графику.. Но делать так с каждой новой версией кода по мере развития темы - извините, в лом. Есть ли более простой способ обеспечить совместимость?
Добавлено через 4 мин. P.S. Я использую gnu в основном.
--------------------
я - ветер, я северный холодный ветер я час расставанья, я год возвращенья домой
Можно попробовать воспользоваться вот этим: http://codecutter.org/tools/winbgim/index.html (сразу говорю: я не пробовал, но положительные отзывы присутствуют. Насколько я помню, даже здесь я приводил эту ссылку уже).
Или написать переходники к основным функциям именно под свой компилятор и под ОС (что там используется из BGI-шного - putpixel и circle? Пока вроде и все)
Но есть еще вероятность, что не все конструкции, пропускаемые TurboC, другие компиляторы будут компилировать (обратное тоже верно, примеры я приводил в начале этой темы). Что с этим делать?
IUnknown, добавил в твой код следующее,глобальную переменную
int dc=1;
В метод Update в конце добавил строку
if (X>maxx+5 || Y<-5) {delete this;dc=0;}
и в цикл запуска всего, просто условие проверки переменной dc и если 0 то заново создать такую же комету, сначала прога работает нормально, но потом через некоторое время вылетает с ненормальным завершением, в чем причина?
Хм... Не знаю, не пробовал делать так, как ты предлагаешь, ибо удалять объект там, где это делаешь ты - не очень хорошая идея. Сделал так: дописал еще один метод в класс Comet:
class Comet : public Celestial { // Все то, что и было, но в public-секции еще:
int OutOfSystem() { return (X < -5 || X > maxx + 5 || Y < -5 || Y > maxy + 5) ? 1 : 0; }
};
// И вот это изменение в Run()
// ...
c_01->Update();
if(c_01->OutOfSystem()) // Проверяем, если вышли за пределы - то пересоздаем комету... { delete c_01; c_01 = new Comet(maxx / 2. - 50, maxy, 2, 0, -5); }
if(kbhit()) ...
, никаких лишних глобальных переменных, ничего больше. Только эти 2 фрагмента. Запустил, уже 20 минут летает, ничего не завершается...
Хм... Не знаю, не пробовал делать так, как ты предлагаешь, ибо удалять объект там, где это делаешь ты - не очень хорошая идея. Сделал так: дописал еще один метод в класс Comet:
class Comet : public Celestial { // Все то, что и было, но в public-секции еще:
int OutOfSystem() { return (X < -5 || X > maxx + 5 || Y < -5 || Y > maxy + 5) ? 1 : 0; }
};
// И вот это изменение в Run()
// ...
c_01->Update();
if(c_01->OutOfSystem()) // Проверяем, если вышли за пределы - то пересоздаем комету... { delete c_01; c_01 = new Comet(maxx / 2. - 50, maxy, 2, 0, -5); }
if(kbhit()) ...
, никаких лишних глобальных переменных, ничего больше. Только эти 2 фрагмента. Запустил, уже 20 минут летает, ничего не завершается...
В одном из фильмов один из героев произнес фразу:"Чувствую себя богом...". А вот моя фраза:"Чувствую себя ЛОХОМ"))))
Спасибо за решение. Твой код почти разобрал. Что не до конца догоню потом спрошу. Жду завтрашнего дня, там выходные можно будет спокойно позаниматься. Буду опять через одно место делать движение планет(в твоем коде)))) После чего только столкновение останется и изменение траектории кометы из за силы притяжения)))
Что именно приводит к вылету программы, добавление движения планеты, или совместное движение планеты и кометы? Я вот сейчас попробовал запустить твою программу, закомментировав в Run() все, что касается кометы - прекрасно крутится зеленый кружок (хотя мне, например, непонятно твое желание просчитать сразу все точки и хранить массив из 720 int-ов, почему не хранить текущий угол поворота, и по нему рассчитывать координаты на каждой итерации?).
Только вот непорядок получается при переходе X от 359 к нулю. Остается артефакт, половина зеленой окружности (нижняя половина) остается на экране. Я бы сделал все-таки вот так:
if (bShow) { if(X == 359) X = Y = 0; Y = X++; }
, тогда по крайней мере артефактов не остается. А вообще - непонятно, почему ты 1) не догадался эти действия производить в методе Recalc(), он же для этого и предназначен: посмотри на Update самого базового класса: сначала гасим изображение, потом пересчитываем то, что нужно пересчитать, и, наконец, проявляем изображение в новом месте. 2) почему до сих пор не догадался, как снять постоянное мерцание Солнца? Оно не должно перерисовываться, у тебя оно все время гасится, потом вызывается пустой Recalc(), потом опять появляется - зачем? Должно быть так: нужно его отобразить один раз, и после этого не гасить и не перерисовывать. Попробуй сделать подобное поведение сам, если не получится - я помогу.
Что именно приводит к вылету программы, добавление движения планеты, или совместное движение планеты и кометы? Я вот сейчас попробовал запустить твою программу, закомментировав в Run() все, что касается кометы - прекрасно крутится зеленый кружок (хотя мне, например, непонятно твое желание просчитать сразу все точки и хранить массив из 720 int-ов, почему не хранить текущий угол поворота, и по нему рассчитывать координаты на каждой итерации?).
Только вот непорядок получается при переходе X от 359 к нулю. Остается артефакт, половина зеленой окружности (нижняя половина) остается на экране. Я бы сделал все-таки вот так:
if (bShow) { if(X == 359) X = Y = 0; Y = X++; }
, тогда по крайней мере артефактов не остается. А вообще - непонятно, почему ты 1) не догадался эти действия производить в методе Recalc(), он же для этого и предназначен: посмотри на Update самого базового класса: сначала гасим изображение, потом пересчитываем то, что нужно пересчитать, и, наконец, проявляем изображение в новом месте. 2) почему до сих пор не догадался, как снять постоянное мерцание Солнца? Оно не должно перерисовываться, у тебя оно все время гасится, потом вызывается пустой Recalc(), потом опять появляется - зачем? Должно быть так: нужно его отобразить один раз, и после этого не гасить и не перерисовывать. Попробуй сделать подобное поведение сам, если не получится - я помогу.
Наверное второе. Хотя заметил так же происходит вылет при столкновении. По поводу хранения угла, как сделаю отпишусь. У меня не доходит до указанного перехода вылетает с Abnormal programm terminated ( заранее извиняюсь за возможно неправильное написание на английском, не владею). По поводу артефакта понял, поправку принял.
По 1) Как переделаю выложу. По 2)
код(Показать/Скрыть)
void Observer :: Run() { sun->Show(1);//<----Вот так сделал while(1) {
earth->Update(); c_01->Update();
if(kbhit()) { if(getch() == 27) break; } if(c_01->OutOfSystem()) // Проверяем, если вышли за пределы - то пересоздаем комету... { delete c_01; c_01 = new Comet(rand()%maxx, maxy, 2, 5, -5); } delay(50); } }
P.S. Вот только не пойму как еще сделать в данном коде разную скорость у планет.
Хм... Хитрый, да? Это не совсем правильное решение Объяснить? Объясняю... Вот этот код, который в Run, нужно будет слегка модифицировать, чтобы отслеживать взаимодействие объектов по схеме "каждое крупное небесное тело с каждой кометой". Для этого удобнее всего будет описать Солнце и планеты не как отдельные экземпляры, а как массив указателей на базовый класс, чтобы потом просто пройти по всему массиву и проверить, как очередной объект взаимодействует с кометой/кометами (если их будет больше одной на экране).
То, что ты сделал - выбивает объект класса Звезда из такой модели. То есть, ты не сможешь просто вызвать Update() в цикле для всех элементов массива КрупныеОбъекты, тебе придется исключать из этого процесса элемент массива, являющийся Солнцем, но проверять на взаимодействие придется со всеми... Опять лишние конструкции, опять if-ы, зачем тебе это? Нужно так модифицировать Star::Show(), чтобы при постоянном вызове Update() не происходило перерисовки объекта
Цитата
Вот только не пойму как еще сделать в данном коде разную скорость у планет.
Вот как переделаешь перемещение планеты через угол (только угол не делай целочисленным, сделай вещественным) - поймешь... Будешь задавать для каждой планеты разное приращение угла - будет разная скорость вращения...
Цитата
У меня не доходит до указанного перехода вылетает с Abnormal programm terminated
Это уже я только завтра/послезавтра смогу потестировать, ноут с Windows уже забрали. Если б тебе хотя бы удалось выяснить, где происходит ошибка - было бы проще...
class Planet : public Celestial { private: int R; const char *name; double Angle;//<----Изменения, естественно в конструкторе тип поменял protected: virtual void Recalc() {}
public: Planet(double px,double py, int psize, int pr, double pangle, const char *pname);
virtual void Show(int); };
Planet :: Planet(double px,double py, int psize, int pr, double pangle, const char *pname) : Celestial(px, py, psize), R(pr), Angle(pangle), name(pname) { #ifdef MSGS cout << "planet " << name << " created (" << R << " " << Angle << " )" << endl; #endif
Обрати внимание на следующие вещи: 1. Все-таки, пересчет планеты я вынес в Recalc() 2. Celestial::Recalc() сделал не чисто виртуальным, а просто пустым, это дало возможность вообще отказаться от реализации этого метода в классе Star, будет использоваться унаследованный из предка. 3. Я не передаю в конструктор планеты начальный угол, пусть все планеты начинают вращение с одним углом (хотя, есть и другие варианты), но я передаю ΔAngle, на который изменяется угол каждую итерацию. Это дает возможность элементарно реализовать не то что разные скорости вращения, а практически реальные, то, что есть на самом деле в Солнечной системе. Просто делишь те самые 360 градусов, которые предстоит пройти планете на ее реальный период обращения в сутках, и получаешь то, что получаешь, я добавил Марс для примера - он, как и положено, вращается один раз, пока Земля делает почти два оборота. Теперь ты понимаешь, зачем я уточнил, что лучше сделать угол вещественным? 4. Что касается Солнца - я тоже сделал так, как задумывалось изначально, чтоб вообще никакого обновления после первого показа не было.
Вроде все, больше ничего не менял.
Ах, да... Мне не удалось дождаться вылета программы: я раскомментировал все строки, касающиеся отображения кометы, и запустил программу. Генерация 30 (тридцати) комет при одновременном вращении двух планет - это достаточное время, чтобы вылет произошел, или надо ждать дольше? Вылета не было...
Обрати внимание на следующие вещи: 1. Все-таки, пересчет планеты я вынес в Recalc() 2. Celestial::Recalc() сделал не чисто виртуальным, а просто пустым, это дало возможность вообще отказаться от реализации этого метода в классе Star, будет использоваться унаследованный из предка. 3. Я не передаю в конструктор планеты начальный угол, пусть все планеты начинают вращение с одним углом (хотя, есть и другие варианты), но я передаю ΔAngle, на который изменяется угол каждую итерацию. Это дает возможность элементарно реализовать не то что разные скорости вращения, а практически реальные, то, что есть на самом деле в Солнечной системе. Просто делишь те самые 360 градусов, которые предстоит пройти планете на ее реальный период обращения в сутках, и получаешь то, что получаешь, я добавил Марс для примера - он, как и положено, вращается один раз, пока Земля делает почти два оборота. Теперь ты понимаешь, зачем я уточнил, что лучше сделать угол вещественным? 4. Что касается Солнца - я тоже сделал так, как задумывалось изначально, чтоб вообще никакого обновления после первого показа не было.
Вроде все, больше ничего не менял.
Ах, да... Мне не удалось дождаться вылета программы: я раскомментировал все строки, касающиеся отображения кометы, и запустил программу. Генерация 30 (тридцати) комет при одновременном вращении двух планет - это достаточное время, чтобы вылет произошел, или надо ждать дольше? Вылета не было...
Разобрал. спасибо. По солнцу, жалко что сам не догадался (. Только не пойму вот что, в чем вот разница объявлений(присваивание 0),
virtual void Show(int) = 0; virtual void Recalc()
Забыл еще спросить по частицам, массив размерностью определенный переменный const int parrSize = 1500; а используется только 100 ?
maxParticles(100)
Ну и нужен совет как дальше делать, столкновение кометы с планетами и солнцем. По поводу вылетов, происходят, может что с ОС на этом ноуте. Хочу потестировать на нетбуке, к вечеру отпишусь