//*************************** File main.c **************************** #include #include "../opsys.h" #include "../Xglib/xglib.h" #include "../Shape2d/application.h" #include "../Shape2d/win_view.h" #include "../Shape2d/mouse.h" #include "../Shape2d/scene.h" #include "../Shape2d/prim.h" #include "../Shape2d/circle.h" #include "../Shape2d/line.h" #include #include #include class ball: public circle_t { public: ball(point_t p, double d, point_t v): circle_t(p,d), velocity(v) {}; ball(mouse_t & m): circle_t(m), velocity(point_t(1.0,1.0)) {}; point_t velocity; // velocity vector: how much to translate in each clock cycle. void step(scene_t *); // take a step. void clip(point_t &, scene_t &); virtual void translate_with_trail(const point_t &, const scene_t &s); }; void ball::translate_with_trail (const point_t & p, const scene_t &s) { point_t old_center = cen; circle_t::translate(p); line_t center_line(old_center,cen); center_line.draw(&s); } enum window_side_t {NoSide, LeftSide, RightSide, BottomSide, TopSide}; void ball::clip(point_t & delta, scene_t & s) { // translate the ball in the direction DELTA by as much as possible // until either we hit the edge of the window or we exhaust DELTA. // If we hit a wall, bounce off it (angle of incidence = angle of reflection) // and call ourselves recursively to continue moving along DELTA in // the new direction. double x = cen.givx(); double y = cen.givy(); double dx = delta.givx(); double dy = delta.givy(); double left = s.givwv()->givleft(); double right = s.givwv()->givright(); double top = s.givwv()->givtop(); double bottom = s.givwv()->givbottom(); window_side_t bestSide = NoSide; // clip against left if ((dx < 0) && ((x+dx) < (left+r))) { dy = dy *((left+r)-x)/dx; dx = (left+r)-x; bestSide = LeftSide; } // clip against right if ((dx > 0) && ((x+dx) > (right-r))) { dy = dy * ((right-r)-x)/dx; dx = (right-r)-x; bestSide = RightSide; } // clip against bottom if ((dy < 0) && ((y+dy) < (bottom+r))) { dx = dx * ((bottom+r)-y)/dy; dy = (bottom+r)-y; bestSide = BottomSide; } // clip against top if ((dy > 0) && ((y+dy) > (top-r))) { dx = dx * ((top-r)-y)/dy; dy = (top-r)-y; bestSide = TopSide; } // Now dx and dy tell how much to move the ball. // Translate it, then compute residual reflected delta. erase(&s); translate_with_trail(point_t(dx,dy), s); draw(&s); flush(); // compute remaining delta delta.setx(delta.givx()-dx); delta.sety(delta.givy()-dy); // now reflect delta to "bounce" the ball. // Change both delta and velocity. switch (bestSide) { case LeftSide: case RightSide: delta.setx(-delta.givx()); velocity.setx(-velocity.givx()); break; case BottomSide: case TopSide: delta.sety(-delta.givy()); velocity.sety(-velocity.givy()); break; case NoSide: break; } if ((delta.givx()!=0) || (delta.givy()!=0)) clip(delta, s); } void ball::step(scene_t * s) { point_t delta=velocity; // copy the velocity clip(delta, *s); } void main() { application_t ap; mouse_t mouse(ap.wv) ; scene_t s(&ap.wv); int code; point_t button; double xvelocity, yvelocity,radius; cout << "Enter radius, xvelocity and yvelocity: "; cin >> radius >> xvelocity >> yvelocity; ball b1(point_t(200.0,200.0), radius, point_t(xvelocity,yvelocity)); b1.draw(&s); flush(); for (;;) { micro_sleep((unsigned int)200000); // sleep for 0.5 seconds while (code = mouse.check_button_down(button)) { if (b1.contains(button)) { mouse.wait_button_click(); } } b1.erase(&s); b1.step(&s); flush(); } } /********************************************************************/