/* * File name: kpacman.cpp * Summary: PacMan animation * License: LGPL - See file COPYING.LIB for details. * Author: Stefan Hundhammer * * Updated: 2004-03-29 */ #include #include #include #include #include #include "kpacman.h" KPacManAnimation::KPacManAnimation( TQWidget * widget, int size, bool randomStart ) { _widget = widget; _size = size; _randomStart = randomStart; _brush = TQBrush( TQt::yellow ); _pos = 0; _speed = 4; _interval = 100; _minMouth = 10; _maxMouth = 70; _mouthInc = ( _maxMouth - _minMouth ) / 3; _mouth = _minMouth; _pacManRect = TQRect( 0, 0, 0, 0 ); restart(); } KPacManAnimation::~KPacManAnimation() { } void KPacManAnimation::restart() { _justStarted = true; if ( _randomStart ) { _goingRight = ( rand() > ( RAND_MAX / 2 ) ); // Initial _pos is set in animate() since the width (upon which it // depends) is still unknown here. } else { _goingRight = true; _pos = 0; } // Care for initial display _time = _time.addMSecs( _interval + 1 ); } void KPacManAnimation::animate( TQPainter * painter, TQRect rect ) { if ( _time.elapsed() < _interval ) return; _time.restart(); // Make PacMan fit into height int size = _size <= rect.height() ? _size : rect.height(); if ( rect.width() < size ) // No space to animate in? return; // -> forget it! if ( _justStarted ) { _justStarted = false; if ( _pacManRect.width() > 0 ) painter->eraseRect( _pacManRect ); if ( _randomStart ) { // Set random initial position // - this depends on the width which is unknown in the constructor. _pos = (int) ( (rect.width() - size ) * ( (double) rand() / RAND_MAX) ); } } else // ! _justStarted { // Erase last PacMan if ( ! _goingRight ) _pacManRect.setX( _pacManRect.x() + _pacManRect.width() - _speed ); _pacManRect.setWidth( _speed ); painter->eraseRect( _pacManRect ); } if ( _pos + size > rect.width() ) // Right edge reached? { // Notice: This can also happen when the rectangle is resized - i.e. it // really makes sense to do that right here rather than at the end of // this function! // Turn left _pos = rect.width() - size; _goingRight = false; _mouth = _minMouth; } else if ( _pos < 0 ) // Left edge reached? { // Turn right _pos = 0; _goingRight = true; _mouth = _minMouth; } // Draw PacMan (double-buffered) _pacManRect = TQRect( 0, 0, size, size ); TQPixmap pixmap( size, size ); pixmap.fill( painter->backgroundColor() ); TQPainter p( &pixmap, _widget ); p.setBrush( _brush ); if ( _goingRight ) { p.drawPie( _pacManRect, _mouth * 16, // arc (1/16 degrees) ( 360 - 2 * _mouth ) * 16 ); // arc length (1/16 degrees) } else { p.drawPie( _pacManRect, ( 180 + _mouth ) * 16, // arc (1/16 degrees) ( 360 - 2 * _mouth ) * 16 ); // arc length (1/16 degrees) } _pacManRect = TQRect( rect.x() + _pos, // x ( rect.height() - size ) / 2, // y size, size ); // width, height // Transfer pixmap into widget #if 0 TQPoint offset = painter->worldMatrix().map( _pacManRect.topLeft() ); // kdDebug() << "bitBlt() to " << offset.x() << ", " << offset.y() << endl; bitBlt( _widget, offset, &pixmap ); #endif painter->drawPixmap( _pacManRect.topLeft(), pixmap ); // Animate mouth for next turn _mouth += _mouthInc; if ( _mouth >= _maxMouth ) // max open reached { _mouth = _maxMouth; _mouthInc = -_mouthInc; // reverse direction } else if ( _mouth <= _minMouth ) // min open reached { _mouth = _minMouth; _mouthInc = -_mouthInc; // reverse direction } // Advance position for next turn if ( _goingRight ) _pos += _speed; else _pos -= _speed; } KPacMan::KPacMan( TQWidget * parent, int pacManSize, bool randomStart, const char * widgetName ) : TQWidget( parent, widgetName ) { _pacManSize = pacManSize; _pacMan = new KPacManAnimation( this, _pacManSize, randomStart ); _timer = 0; _interval = 100; // millisec _active = false; _painter = new TQPainter( this ); _margin = 1; } KPacMan::~KPacMan() { if ( _painter ) delete _painter; if ( _pacMan ) delete _pacMan; } void KPacMan::start() { if ( ! _timer ) { _timer = new TQTimer( this ); } _pacMan->restart(); if ( _timer ) { _active = true; _timer->start( _interval ); connect( _timer, TQ_SIGNAL( timeout() ), this, TQ_SLOT ( animate() ) ); } } void KPacMan::stop() { _active = false; if ( _timer ) _timer->stop(); repaint(); } void KPacMan::animate() { repaint( false ); } void KPacMan::setInterval( int intervalMilliSec ) { _interval = intervalMilliSec; _pacMan->setInterval( _interval ); if ( _timer ) _timer->changeInterval( _interval ); } void KPacMan::paintEvent( TQPaintEvent *ev ) { TQWidget::paintEvent( ev ); if ( _active ) { _pacMan->animate( _painter, TQRect( _margin, 0, width() - _margin, height() ) ); } } void KPacMan::mouseReleaseEvent ( TQMouseEvent *ev ) { if ( _active ) { if ( _pacMan->lastPacMan().contains( ev->pos() ) ) stop(); } } TQSize KPacMan::sizeHint() const { return TQSize( 16 * _pacManSize, // width - admittedly somewhat random _pacManSize + 2 * _margin ); // height } #include "kpacman.moc" // EOF