#include #include #include class Logo : public QCanvasSprite { void initPos() { initSpeed(); int trial=1000; do { move(rand()%(canvas()->width()-width()),rand()%(canvas()->height()-height())); advance(0); } while (trial-- && xVelocity()==0.0 && yVelocity()==0.0); } void initSpeed() { const double speed = 4.0; double d = (double)(rand()%1024) / 1024.0; setVelocity( d*speed*2-speed, (1-d)*speed*2-speed ); } public: Logo( QCanvasPixmapArray* pm, QCanvas* c ) : QCanvasSprite( pm, c ) { setAnimated(TRUE); initPos(); } void advance( int stage ) { switch ( stage ) { case 0: { double vx = xVelocity(); double vy = yVelocity(); // we are too slow, reinitialize speed if ( QABS( vx ) < 0.1 && QABS(vy) < 0.1 ) { initSpeed(); vx = xVelocity(); vy = yVelocity(); } // whenever we hit a wall, turn around if ( x()+vx < 0 || x()+width()+vx >= canvas()->width() ) vx = -vx; if ( y()+vy < 0 || y()+height()+vy >= canvas()->height() ) vy = -vy; // test all four directions and bounce if possible. If // not, slow down for (int bounce=0; bounce<4; bounce++) { QCanvasItemList l=collisions(FALSE); for (QCanvasItemList::Iterator it=l.begin(); it!=l.end(); ++it) { if ( (*it)->collidesWith(this) ) { switch ( bounce ) { case 0: vx = -vx; break; case 1: vy = -vy; vx = -vx; break; case 2: vx = -vx; break; case 3: vx /= 2; vy /= 2; break; } setVelocity(vx,vy); break; } } } // we still would hit a wall, slow down speed if ( x()+vx < 0 || x()+width()+vx >= canvas()->width() ) vx /= 2; if ( y()+vy < 0 || y()+height()+vy >= canvas()->height() ) vy /= 2; setVelocity(vx,vy); } break; case 1: QCanvasItem::advance(stage); break; } } }; int main( int argc, char* argv[] ) { QApplication a( argc, argv ); QCanvas canvas( 800, 600 ); QCanvasPixmapArray pm("qtlogo.png" ); for ( int i = 0; i < 6; i++ ) (new Logo( &pm, &canvas ) )->show(); canvas.setAdvancePeriod(30); QCanvasView cview( &canvas ); a.setMainWidget( &cview ); cview.setCaption( "Bouncing Qt logos"); cview.show(); return a.exec(); }