Logo Search packages:      
Sourcecode: k4dirstat version File versions  Download package

kpacman.cpp

/*
 *   File name:   kpacman.cpp
 *   Summary:     PacMan animation
 *   License:     LGPL - See file COPYING.LIB for details.
 *   Author:      Stefan Hundhammer <sh@suse.de>
 *              Joshua Hodosh <kdirstat@grumpypenguin.org>
 *
 *   Updated:     2010-02-01
 */


#ifdef HAVE_CONFIG_H
#   include <config.h>
#endif

#include <unistd.h>
#include <stdlib.h>
#include <qtimer.h>
#include <qpixmap.h>
#include <kdebug.h>
#include <QMouseEvent>

#include "kpacman.h"


00026 KPacManAnimation::KPacManAnimation( QWidget *   widget,
                            int           size,
                            bool    randomStart )
{
    _widget       = widget;
    _size         = size;
    _randomStart  = randomStart;
    _brush        = QBrush( Qt::yellow );
    _pos          = 0;
    _speed        = 4;
    _interval           = 100;

    _minMouth           = 10;
    _maxMouth           = 70;
    _mouthInc           = ( _maxMouth - _minMouth ) / 3;
    _mouth        = _minMouth;
    _pacManRect         = QRect( 0, 0, 0, 0 );

    restart();
}


00048 KPacManAnimation::~KPacManAnimation()
{
}


void
00054 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
00077 KPacManAnimation::animate( Q3Painter *    painter,
                     QRect    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 = QRect( 0, 0, size, size );
    QPixmap pixmap( size, size );
    pixmap.fill( painter->backgroundColor() );
    Q3Painter p( &pixmap);

    p.setBrush( _brush );

    if ( _goingRight )
    {
      p.drawPie( _pacManRect,
               _mouth * 16,                     // arc (1/16 degrees)
               ( 360 - 2 * _mouth ) * 16 );           // arc lenght (1/16 degrees)
    }
    else
    {
      p.drawPie( _pacManRect,
               ( 180 + _mouth ) * 16,           // arc (1/16 degrees)
               ( 360 - 2 * _mouth ) * 16 );           // arc lenght (1/16 degrees)
    }

    _pacManRect = QRect( rect.x() + _pos,       // x
                   ( rect.height() - size ) / 2,      // y
                   size, size );                // width, height

    // Transfer pixmap into widget

#if 0
    QPoint 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;
}






00209 KPacMan::KPacMan( QWidget *   parent,
              int             pacManSize,
              bool            randomStart,
              const char *    widgetName )
    : QWidget( parent, widgetName )
{
    _pacManSize   = pacManSize;
    _pacMan       = new KPacManAnimation( this, _pacManSize, randomStart );
    _timer  = 0;
    _interval     = 100;      // millisec
    _active = false;
    _painter      = new Q3Painter( this );
    _margin = 1;
}


00225 KPacMan::~KPacMan()
{
    if ( _painter )
      delete _painter;

    if ( _pacMan )
      delete _pacMan;
}


void
00236 KPacMan::start()
{
    if ( ! _timer )
    {
      _timer = new QTimer( this );
    }

    _pacMan->restart();

    if ( _timer )
    {
      _active = true;
      _timer->start( _interval );
      connect( _timer, SIGNAL( timeout() ),
             this,   SLOT  ( animate() ) );
    }
}


void
00256 KPacMan::stop()
{
    _active = false;

    if ( _timer )
      _timer->stop();

    repaint();
}


void
00268 KPacMan::animate()
{
    repaint( false );
}


void
00275 KPacMan::setInterval( int intervalMilliSec )
{
    _interval = intervalMilliSec;
    _pacMan->setInterval( _interval );

    if ( _timer )
      _timer->changeInterval( _interval );
}


void
00286 KPacMan::paintEvent( QPaintEvent *ev )
{
    QWidget::paintEvent( ev );
    
    if ( _active )
    {
      _pacMan->animate( _painter, QRect( _margin, 0, width() - _margin, height() ) );
    }
}


void
00298 KPacMan::mouseReleaseEvent ( QMouseEvent *ev )
{
    if ( _active )
    {
      if ( _pacMan->lastPacMan().contains( ev->pos() ) )
          stop();
    }
}


QSize
00309 KPacMan::sizeHint() const
{
    return QSize( 16 * _pacManSize,       // width - admittedly somewhat random
              _pacManSize + 2 * _margin );      // height
}



// EOF

Generated by  Doxygen 1.6.0   Back to index