KDirStat – a graphical disk usage utility
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.

312 lines
5.5KB

  1. /*
  2. * File name: kpacman.cpp
  3. * Summary: PacMan animation
  4. * License: LGPL - See file COPYING.LIB for details.
  5. * Author: Stefan Hundhammer <sh@suse.de>
  6. *
  7. * Updated: 2004-03-29
  8. */
  9. #include <unistd.h>
  10. #include <stdlib.h>
  11. #include <tqtimer.h>
  12. #include <tqpixmap.h>
  13. #include <kdebug.h>
  14. #include "kpacman.h"
  15. KPacManAnimation::KPacManAnimation( TQWidget * widget,
  16. int size,
  17. bool randomStart )
  18. {
  19. _widget = widget;
  20. _size = size;
  21. _randomStart = randomStart;
  22. _brush = TQBrush( TQt::yellow );
  23. _pos = 0;
  24. _speed = 4;
  25. _interval = 100;
  26. _minMouth = 10;
  27. _maxMouth = 70;
  28. _mouthInc = ( _maxMouth - _minMouth ) / 3;
  29. _mouth = _minMouth;
  30. _pacManRect = TQRect( 0, 0, 0, 0 );
  31. restart();
  32. }
  33. KPacManAnimation::~KPacManAnimation()
  34. {
  35. }
  36. void
  37. KPacManAnimation::restart()
  38. {
  39. _justStarted = true;
  40. if ( _randomStart )
  41. {
  42. _goingRight = ( rand() > ( RAND_MAX / 2 ) );
  43. // Initial _pos is set in animate() since the width (upon which it
  44. // depends) is still unknown here.
  45. }
  46. else
  47. {
  48. _goingRight = true;
  49. _pos = 0;
  50. }
  51. // Care for initial display
  52. _time = _time.addMSecs( _interval + 1 );
  53. }
  54. void
  55. KPacManAnimation::animate( TQPainter * painter,
  56. TQRect rect )
  57. {
  58. if ( _time.elapsed() < _interval )
  59. return;
  60. _time.restart();
  61. // Make PacMan fit into height
  62. int size = _size <= rect.height() ? _size : rect.height();
  63. if ( rect.width() < size ) // No space to animate in?
  64. return; // -> forget it!
  65. if ( _justStarted )
  66. {
  67. _justStarted = false;
  68. if ( _pacManRect.width() > 0 )
  69. painter->eraseRect( _pacManRect );
  70. if ( _randomStart )
  71. {
  72. // Set random initial position
  73. // - this depends on the width which is unknown in the constructor.
  74. _pos = (int) ( (rect.width() - size ) * ( (double) rand() / RAND_MAX) );
  75. }
  76. }
  77. else // ! _justStarted
  78. {
  79. // Erase last PacMan
  80. if ( ! _goingRight )
  81. _pacManRect.setX( _pacManRect.x() + _pacManRect.width() - _speed );
  82. _pacManRect.setWidth( _speed );
  83. painter->eraseRect( _pacManRect );
  84. }
  85. if ( _pos + size > rect.width() ) // Right edge reached?
  86. {
  87. // Notice: This can also happen when the rectangle is resized - i.e. it
  88. // really makes sense to do that right here rather than at the end of
  89. // this function!
  90. // Turn left
  91. _pos = rect.width() - size;
  92. _goingRight = false;
  93. _mouth = _minMouth;
  94. }
  95. else if ( _pos < 0 ) // Left edge reached?
  96. {
  97. // Turn right
  98. _pos = 0;
  99. _goingRight = true;
  100. _mouth = _minMouth;
  101. }
  102. // Draw PacMan (double-buffered)
  103. _pacManRect = TQRect( 0, 0, size, size );
  104. TQPixmap pixmap( size, size );
  105. pixmap.fill( painter->backgroundColor() );
  106. TQPainter p( &pixmap, _widget );
  107. p.setBrush( _brush );
  108. if ( _goingRight )
  109. {
  110. p.drawPie( _pacManRect,
  111. _mouth * 16, // arc (1/16 degrees)
  112. ( 360 - 2 * _mouth ) * 16 ); // arc length (1/16 degrees)
  113. }
  114. else
  115. {
  116. p.drawPie( _pacManRect,
  117. ( 180 + _mouth ) * 16, // arc (1/16 degrees)
  118. ( 360 - 2 * _mouth ) * 16 ); // arc length (1/16 degrees)
  119. }
  120. _pacManRect = TQRect( rect.x() + _pos, // x
  121. ( rect.height() - size ) / 2, // y
  122. size, size ); // width, height
  123. // Transfer pixmap into widget
  124. #if 0
  125. TQPoint offset = painter->worldMatrix().map( _pacManRect.topLeft() );
  126. // kdDebug() << "bitBlt() to " << offset.x() << ", " << offset.y() << endl;
  127. bitBlt( _widget, offset, &pixmap );
  128. #endif
  129. painter->drawPixmap( _pacManRect.topLeft(), pixmap );
  130. // Animate mouth for next turn
  131. _mouth += _mouthInc;
  132. if ( _mouth >= _maxMouth ) // max open reached
  133. {
  134. _mouth = _maxMouth;
  135. _mouthInc = -_mouthInc; // reverse direction
  136. }
  137. else if ( _mouth <= _minMouth ) // min open reached
  138. {
  139. _mouth = _minMouth;
  140. _mouthInc = -_mouthInc; // reverse direction
  141. }
  142. // Advance position for next turn
  143. if ( _goingRight )
  144. _pos += _speed;
  145. else
  146. _pos -= _speed;
  147. }
  148. KPacMan::KPacMan( TQWidget * parent,
  149. int pacManSize,
  150. bool randomStart,
  151. const char * widgetName )
  152. : TQWidget( parent, widgetName )
  153. {
  154. _pacManSize = pacManSize;
  155. _pacMan = new KPacManAnimation( this, _pacManSize, randomStart );
  156. _timer = 0;
  157. _interval = 100; // millisec
  158. _active = false;
  159. _painter = new TQPainter( this );
  160. _margin = 1;
  161. }
  162. KPacMan::~KPacMan()
  163. {
  164. if ( _painter )
  165. delete _painter;
  166. if ( _pacMan )
  167. delete _pacMan;
  168. }
  169. void
  170. KPacMan::start()
  171. {
  172. if ( ! _timer )
  173. {
  174. _timer = new TQTimer( this );
  175. }
  176. _pacMan->restart();
  177. if ( _timer )
  178. {
  179. _active = true;
  180. _timer->start( _interval );
  181. connect( _timer, TQT_SIGNAL( timeout() ),
  182. this, TQT_SLOT ( animate() ) );
  183. }
  184. }
  185. void
  186. KPacMan::stop()
  187. {
  188. _active = false;
  189. if ( _timer )
  190. _timer->stop();
  191. repaint();
  192. }
  193. void
  194. KPacMan::animate()
  195. {
  196. repaint( false );
  197. }
  198. void
  199. KPacMan::setInterval( int intervalMilliSec )
  200. {
  201. _interval = intervalMilliSec;
  202. _pacMan->setInterval( _interval );
  203. if ( _timer )
  204. _timer->changeInterval( _interval );
  205. }
  206. void
  207. KPacMan::paintEvent( TQPaintEvent *ev )
  208. {
  209. TQWidget::paintEvent( ev );
  210. if ( _active )
  211. {
  212. _pacMan->animate( _painter, TQRect( _margin, 0, width() - _margin, height() ) );
  213. }
  214. }
  215. void
  216. KPacMan::mouseReleaseEvent ( TQMouseEvent *ev )
  217. {
  218. if ( _active )
  219. {
  220. if ( _pacMan->lastPacMan().contains( ev->pos() ) )
  221. stop();
  222. }
  223. }
  224. TQSize
  225. KPacMan::sizeHint() const
  226. {
  227. return TQSize( 16 * _pacManSize, // width - admittedly somewhat random
  228. _pacManSize + 2 * _margin ); // height
  229. }
  230. #include "kpacman.moc"
  231. // EOF