#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() = 0; 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 { public: Star(int psize) : Celestial(maxx / 2, maxy / 2, psize) { #ifdef MSGS cout << "star created" << endl; #endif } virtual void Show(int); virtual void Recalc() {} }; void Star :: Show(int bShow) { setcolor( bShow ? YELLOW : getbkcolor() ); circle((int)X, (int)Y, Size); } Star *sun; class Planet : public Celestial { private: int R, Angle; const char *name; protected: virtual void Recalc() {} public: Planet(double px, double py, int psize, int pr, int pangle, const char *pname); virtual void Show(int); }; Planet :: Planet(double px, double py, int psize, int pr, int pangle, const char *pname) : Celestial(px, py, psize), R(pr), Angle(pangle), name(pname) { #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); }; Planet *earth; 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 > 40 * 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, ""); 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(); c_01->Update(); if(kbhit()) { if(getch() == 27) break; } delay(150); } } int main() { Observer obj; sun = new Star(10); earth = new Planet(maxx / 2., maxy / 2. + 3 * 20, 3, maxy / 2. + 3 * 20, 0, "earth"); c_01 = new Comet(maxx / 2. - 50, maxy, 2, 0, -5); obj.Run(); return 0; }