#define MSGS_OFF #include #include #include #include #include #include int maxx; int maxy; class Celestial { protected: double X, Y; int Size; virtual void Show(int) = 0; virtual void Recalc() { } public: Celestial(double px, double py, int psize); double getX() const { return X; } double getY() const { return Y; } int getSize() const { return Size; } void Update(); }; Celestial :: Celestial(double px, double py, int psize) : X(px), Y(py), Size(psize) { #ifdef MSGS cout << "Celestial created (" << X << " " << Y << " " << Size << " )" << endl; #endif } void Celestial :: Update() { Show(0); Recalc(); Show(1); } double dist(Celestial &a, Celestial &b) { double dx = a.getX() - b.getX(); double dy = a.getY() - b.getY(); return sqrt(dx * dx + dy * dy); } class Star : public Celestial { int Shown; public: Star(int psize) : Celestial(maxx / 2, maxy / 2, psize), Shown(0) { #ifdef MSGS cout << "star created" << endl; #endif } virtual void Show(int); }; void Star :: Show(int bShow) { if(!Shown) { setcolor( bShow ? (Shown = 1, YELLOW) : getbkcolor() ); circle((int)X, (int)Y, Size); } } Star *sun; class Planet : public Celestial { private: int R; const char *name; double Angle, DeltaAngle; //<----Изменения, естественно в конструкторе тип поменял protected: virtual void Recalc() { Angle -= DeltaAngle; if(Angle < 0) Angle += 360; X = maxx/2 + R*cos(Angle*M_PI/180); //<----Изменения Y = maxy/2 + R*sin(Angle*M_PI/180); // } public: Planet(double px, double py, int psize, int pr, double pdeltaangle, const char *pname); virtual void Show(int); }; Planet :: Planet(double px,double py, int psize, int pr, double pdeltaangle, const char *pname) : Celestial(px, py, psize), R(pr), Angle(360), name(pname), DeltaAngle(pdeltaangle) { #ifdef MSGS cout << "planet " << name << " created (" << R << " " << Angle << " )" << endl; #endif } void Planet :: Show(int bShow) { setcolor( bShow ? LIGHTGREEN : getbkcolor() ); circle((int)X, (int)Y, Size); } class Particle : public Celestial { private: double Vx, Vy; public: Particle(double px, double py, double pvx, double pvy); ~Particle(); virtual void Show(int); virtual void Recalc(); }; Particle :: Particle(double px, double py, double pvx, double pvy) : Celestial(px, py, 1), Vx(pvx), Vy(pvy) { #ifdef MSGS cout << "particle created : Vx = " << Vx << " Vy = " << Vy << endl; #endif } Particle :: ~Particle() { Show(0); } void Particle :: Show(int bShow) { putpixel( (int)X, (int)Y, bShow ? LIGHTGRAY : getbkcolor() ); } void Particle :: Recalc() { Vx += ((getX() - sun->getX()) / dist(*sun, *this)); Vy += ((getY() - sun->getY()) / dist(*sun, *this)); X += Vx; Y += Vy; } const int parrSize = 1500; const int stepParticles = 15; const int maxPartSpeed = 3; class Comet : public Celestial { private: double Ex, Ey; int Vx, Vy; Particle *trace[parrSize]; int maxParticles; private: int Cvt(int curr); protected: virtual void Recalc(); public: Comet(double px, double py, int psize, int pvx, int pvy); virtual void Show(int); int OutOfSystem() { return (X < -5 || X > maxx + 5 || Y < -5 || Y > maxy + 5) ? 1 : 0; } }; Planet *earth, *mars; Comet *c_01; int Comet :: Cvt(int curr) { int sign; if(!curr) sign = 0; else sign = curr / abs(curr); return sign * random(maxPartSpeed - abs(curr)); } Comet :: Comet(double px, double py, int psize, int pvx, int pvy) : Celestial(px, py, psize), Vx(pvx), Vy(pvy), maxParticles(100) { Ex = (sun->getX() - sun->getSize()) / maxPartSpeed; Ey = (sun->getY() - sun->getSize()) / maxPartSpeed; for(int i = 0; i < maxParticles; i++) { double dx = (px - sun->getX()); double dy = (py - sun->getY()); #ifdef MSGS cout << "i = " << i << " Dx = " << dx << " Dy = " << dy << endl; #endif trace[i] = new Particle(px - 1 + random(2), py - 1 + random(2), Vx + Cvt((int)(dx / Ex)) - 1 + random(2), Vy + Cvt((int)(dy / Ey)) - 1 + random(2)); } #ifdef MSGS cout << "comet created (" << Vx << " " << Vy << " )" << endl; cout << "dist to sun = " << dist(*sun, *this) << endl; #endif } void Comet :: Recalc() { X += Vx; Y += Vy; #ifdef MSGS cout << "comet : dist to sun = " << dist(*sun, *this) << endl; #endif int count = 0; for(int i = 0; i < maxParticles; i++) { trace[i]->Recalc(); double d = dist(*trace[i], *this); #ifdef MSGS cout << "i = " << i << " Dist = " << d << endl; #endif if(d > 25 * Size) { delete trace[i]; count += 1; trace[i] = new Particle((int)(getX()) - 1 + random(2), (int)(getY()) - 1 + random(2), Vx + Cvt((int)((getX() - sun->getX()) / Ex)) - 1 + random(2), Vy + Cvt((int)((getY() - sun->getY()) / Ey)) - 1 + random(2)); } } #ifdef MSGS cout << count << " new particles created" << endl; #endif for(i = 0; i <= stepParticles - count; i++) { trace[maxParticles + i] = new Particle((int)(getX()) - 1 + random(2), (int)(getY()) - 1 + random(2), Vx + Cvt((int)((getX() - sun->getX()) / Ex)) - 1 + random(2), Vy + Cvt((int)((getY() - sun->getY()) / Ey)) - 1 + random(2)); } if(stepParticles - count > 0) maxParticles += (stepParticles - count); #ifdef MSGS cout << maxParticles << " currently. Max = " << parrSize << endl; #endif } void Comet :: Show(int bShow) { setcolor( bShow ? WHITE : getbkcolor() ); circle((int)X, (int)Y, Size); for(int i = 0; i < maxParticles; i++) trace[i]->Show(bShow); } class Observer { public: Observer(); ~Observer(); void Run(); }; Observer :: Observer() { int gdriver = DETECT, gmode, errorcode; initgraph(&gdriver, &gmode, "../BGI"); errorcode = graphresult(); if(errorcode != grOk) { cerr << "Graphics error: " << grapherrormsg(errorcode) << endl; exit(-1); } maxx = getmaxx(); maxy = getmaxy(); randomize(); } Observer :: ~Observer() { closegraph(); } void Observer :: Run() { while(1) { sun->Update(); earth->Update(); mars->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(5); } } int main() { Observer obj; sun = new Star(10); earth = new Planet(maxx / 2.+ 3 * 20, maxy / 2., 3, 60, 360./365., "earth"); mars = new Planet(maxx / 2.+ 4 * 20, maxy / 2., 3, 80, 360./687., "mars"); //c_01 = new Comet(rand()%maxx, maxy, 2, 5, -5); obj.Run(); return 0; }