home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / ocl_ani1.zip / ocl_ani1.cpp < prev    next >
Text File  |  1997-06-19  |  5KB  |  191 lines

  1. /* Stéphane Charette, scharett@vansel.alcatel.com
  2.  * IBM Open Class Library Animation Sample
  3.  * (using Visual Age C++ v3.0 with OS/2 v4.0)
  4.  * 1997June19
  5.  */
  6.  
  7. /* local include */
  8. #include "ocl_ani1.hpp"
  9.  
  10. /* function prototypes */
  11. int main( void );
  12.  
  13. /* global variables */
  14. IDrawingCanvas *canvas;
  15. IFrameWindow *frameDlg;
  16. Ball *bitmap;
  17. IGList *glist;
  18. ITimer *timer;
  19.  
  20. /*
  21.  * main
  22.  */
  23. int main()
  24. {
  25.    // create the frame window
  26.    frameDlg = new IFrameWindow( DIALOG_RCID );
  27.  
  28.    // set the icon for the window
  29.    frameDlg->setIcon( DIALOG_RCID );
  30.  
  31.    // create the drawing canvas
  32.    canvas = new IDrawingCanvas(  CANVAS_RCID,         // id
  33.                                  frameDlg,            // parent
  34.                                  frameDlg,            // owner
  35.                                  frameDlg->clientRectFor( frameDlg->rect() ) );
  36.  
  37.    // set the background color
  38.    canvas->setBackgroundColor( IColor::white );
  39.  
  40.    // add the drawing canvas to the frame
  41.    frameDlg->setClient( canvas );
  42.  
  43.    // show the window
  44.    frameDlg->show();
  45.  
  46.    // add the title to the window list
  47.    frameDlg->addToWindowList();
  48.  
  49.    // create the bitmap object
  50.    bitmap = new Ball( BMP_BALL_RCID );
  51.  
  52.    // position the object at the lower-left corner of canvas
  53.    bitmap->moveTo( canvas->rect().bottomLeft() );
  54.    bitmap->x = bitmap->position().x();
  55.    bitmap->y = bitmap->position().y();
  56.  
  57.    // create the graphic list with the object
  58.    glist = new IGList( *bitmap );
  59.  
  60.    // associate the list to the drawing canvas
  61.    canvas->setGraphicList( glist );
  62.  
  63.    // start the timer
  64.    timer = new ITimer( new ITimerMemberFn0<Ball>(*bitmap,Ball::calcNextMove), 50 );
  65.  
  66.    // run the application
  67.    IApplication::current().run();
  68.  
  69.    // window has exited
  70.    frameDlg->removeFromWindowList();
  71.    frameDlg->hide();
  72.    delete( timer );
  73.    delete( canvas );
  74.    delete( glist );
  75.    delete( bitmap );
  76.    delete( frameDlg );
  77.  
  78.    // return to the O/S
  79.    return 0;
  80. }
  81.  
  82.  
  83.  
  84. Ball::Ball( USHORT rcid ) : IGBitmap( rcid )
  85. {
  86.       /* At the moment, the speed, angle, deltaX and deltaY are all
  87.        * set once at the beginning of the application.  My goal was
  88.        * to make it as easy as possible to add some window controls
  89.        * (spinbuttons, etc) to change these values dynamically while
  90.        * the application is running.
  91.        */
  92.    speed = 15.0;
  93.    angle = 30.0;
  94.    x = 0.0;
  95.    y = 0.0;
  96.    dx = 0.0;
  97.    dy = 0.0;
  98.  
  99.    // calculate the deltas
  100.    dx = cos( convertDegToRad(angle) ) * speed;
  101.    dy = sin( convertDegToRad(angle) ) * speed;
  102.  
  103.    return;
  104. }
  105.  
  106.  
  107.  
  108. void Ball::calcNextMove()
  109. {
  110.    IRectangle originalRect, newRect;   // bounding rectangles used to refresh
  111.    IPoint newPos;                      // new bitmap position
  112.  
  113.    // get the graphic context
  114.    IGraphicContext *graphicContext = new IGraphicContext(canvas->handle());
  115.  
  116.    // find the original bounding rectangle (needed when it comes time to refresh)
  117.    originalRect = bitmap->boundingRect(*graphicContext);
  118.  
  119.    // find the new location
  120.    x += dx;
  121.    y += dy;
  122.    newPos.setX( (long)x ).setY( (long)y );
  123.  
  124.    // move the bitmap
  125.    bitmap->moveTo( newPos );
  126.  
  127.    // calculate the new bounding rectangle
  128.    newRect = bitmap->boundingRect(*graphicContext);
  129.  
  130.    // is the new location valid?
  131.    if( ! canvas->rect().contains( newRect ) )
  132.    {
  133.       // we've gone beyond the bounds...calculate a new position and angle!
  134.       IPoint position = bitmap->position();
  135.  
  136.       // is the left side off the canvas?
  137.       if( position.x() < canvas->rect().left() )
  138.       {
  139.          position.setX( canvas->rect().left() );
  140.          dx = - dx;
  141.       }
  142.       // is the bottom off the canvas?
  143.       if( position.y() < canvas->rect().bottom() )
  144.       {
  145.          position.setY( canvas->rect().bottom() );
  146.          dy = - dy;
  147.       }
  148.       // is the right side off the canvas?
  149.       if( position.x() + newRect.width() > canvas->rect().right() )
  150.       {
  151.          position.setX( canvas->rect().right() - newRect.width() );
  152.          dx = - dx;
  153.       }
  154.       // is the top off the canvas?
  155.       if( position.y() + newRect.height() > canvas->rect().top() )
  156.       {
  157.          position.setY( canvas->rect().top() - newRect.height() );
  158.          dy = - dy;
  159.       }
  160.  
  161.       // move the bitmap
  162.       bitmap->moveTo( position );
  163.  
  164.       // make sure we know where our bitmap is located
  165.       bitmap->x = bitmap->position().x();
  166.       bitmap->y = bitmap->position().y();
  167.  
  168.       // calculate the new bounding rectangle
  169.       newRect = bitmap->boundingRect(*graphicContext);
  170.    }
  171.  
  172.    // delete the graphic context used to get the rectangles
  173.    delete( graphicContext );
  174.  
  175.    // figure out the maximum rectangle of the screen that needs updating
  176.    _RECTL rectl = ( originalRect | newRect ).expandBy(1).asRECTL();
  177.       /* I'm not certain why I have to do ".expandBy(1)" for
  178.        * this to work correctly...if it isn't there, then the
  179.        * ball will leave "tracks" every once in a while when
  180.        * it moves around the window.  I thought that finding
  181.        * the old and new bounding rectangles would be enough,
  182.        * but somehow it isn't...
  183.        */
  184.  
  185.    // tell PM what part of the screen needs to be refreshed
  186.    WinInvalidateRect( canvas->handle(), &rectl, FALSE );
  187.  
  188.    return;
  189. }
  190.  
  191.