You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
kdirstat/kdirstat/kpacman.cpp

312 lines
5.5 KiB

/*
* File name: kpacman.cpp
* Summary: PacMan animation
* License: LGPL - See file COPYING.LIB for details.
* Author: Stefan Hundhammer <sh@suse.de>
*
* Updated: 2004-03-29
*/
#include <unistd.h>
#include <stdlib.h>
#include <tqtimer.h>
#include <tqpixmap.h>
#include <kdebug.h>
#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, TQT_SIGNAL( timeout() ),
this, TQT_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
}
// EOF