• Skip to content
  • Skip to link menu
KDE 4.0 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

kgoldrunner

kgrcanvas.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002                           kgrcanvas.cpp  -  description
00003                              -------------------
00004     begin                : Wed Jan 23 2002
00005     Copyright 2002 Marco Krüger <grisuji@gmx.de>
00006     Copyright 2002 Ian Wadham <ianw2@optusnet.com.au>
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  *                                                                         *
00011  *   This program is free software; you can redistribute it and/or modify  *
00012  *   it under the terms of the GNU General Public License as published by  *
00013  *   the Free Software Foundation; either version 2 of the License, or     *
00014  *   (at your option) any later version.                                   *
00015  *                                                                         *
00016  ***************************************************************************/
00017 
00018 #include "kgrcanvas.h"
00019 
00020 #include <QPixmap>
00021 #include <QList>
00022 #include <QLabel>
00023 #include <QMouseEvent>
00024 
00025 #include <KDebug>
00026 
00027 #include <KConfig>
00028 
00029 #include <cmath>
00030 
00031 KGrCanvas::KGrCanvas (QWidget * parent, const double scale,
00032             const QString & systemDataDir)
00033             : KGameCanvasWidget (parent),
00034               topLeft (0, 0), bgw (4 * STEP), bgh (4 * STEP),
00035               m_fadingTimeLine(1000, this),
00036               theme(systemDataDir)
00037 {
00038     resizeCount = 0;        // Do not render or paint until resize is done.
00039 
00040     kDebug() << "Called KGrCanvas::KGrCanvas ..." << this->size();
00041     m = new QCursor ();     // For handling the mouse.
00042 
00043     // The default background is black.  It appears during partial repaints.
00044     setPalette(QPalette(Qt::black));
00045     setAutoFillBackground(true);
00046 
00047     scaleStep = STEP;       // Initial scale is 1:1.
00048     baseScale = scaleStep;
00049     baseFontSize = fontInfo().pointSize() + 2;
00050     scaleStep = (int) ((scale * STEP) + 0.05);
00051     kDebug() << "Scale" << scale << "Scaled Step" << scaleStep;
00052 
00053     nCellsW = FIELDWIDTH;
00054     nCellsH = FIELDHEIGHT;
00055     border = 4;         // Make border at least tiles wide all around.
00056     lineDivider = 8;        // Make lines of inner border 1/8 tile wide.
00057 
00058     heroSprite = 0;
00059 
00060     // Create an empty list of enemy sprites.
00061     enemySprites = new QList<KGrSprite *> ();
00062 
00063     kDebug() << "Calling initView() ...";
00064     initView();         // Set up the graphics, etc.
00065 
00066     // Initialise the KGoldrunner grid.
00067     for (int x = 0; x < FIELDWIDTH; x++) {
00068     for (int y = 0; y < FIELDHEIGHT; y++) {
00069         tileNo[x][y] = freebg;
00070     }
00071     }
00072 
00073     title = 0;
00074     level = 0;
00075 
00076     // Set minimum size to 12x12 pixels per tile.
00077     setMinimumSize((FIELDWIDTH + 4) * 12, (FIELDHEIGHT + 4) * 12);
00078 
00079     m_spotLight = new KGameCanvasPicture(this);
00080     m_fadingTimeLine.setCurveShape(QTimeLine::LinearCurve);
00081     m_fadingTimeLine.setUpdateInterval( 80 );
00082     connect(&m_fadingTimeLine, SIGNAL(valueChanged(qreal)),
00083         this, SLOT(drawSpotLight(qreal)));
00084 }
00085 
00086 KGrCanvas::~KGrCanvas()
00087 {
00088     tileset->clear();
00089     heroFrames->clear();
00090     enemyFrames->clear();
00091     delete tileset;
00092     delete heroFrames;
00093     delete enemyFrames;
00094     delete m_spotLight;
00095 }
00096 
00097 void KGrCanvas::goToBlack()
00098 {
00099     drawSpotLight (0);
00100 }
00101 
00102 void KGrCanvas::fadeIn()
00103 {
00104     m_fadingTimeLine.setDirection(QTimeLine::Forward);
00105     m_fadingTimeLine.start();
00106 }
00107 
00108 void KGrCanvas::fadeOut()
00109 {
00110     m_fadingTimeLine.setDirection(QTimeLine::Backward);
00111     m_fadingTimeLine.start();
00112 }
00113 
00114 void KGrCanvas::drawTheScene (bool changePixmaps)
00115 {
00116     t.restart();
00117     kDebug() << 0 << "msec.  Start KGrCanvas::drawTheScene";
00118 
00119     // The pixmaps for tiles and sprites have to be re-loaded
00120     // if and only if the theme or the cell size has changed.
00121 
00122     // The background has to be re-loaded if the theme has
00123     // changed, the cell size has changed or the canvas size
00124     // has changed and the bg must fill it (! themeDrawBorder).
00125 
00126     double scale = (double) imgW / (double) bgw;
00127     kDebug() << "Called KGrCanvas::drawTheScene() - Images:" << imgW<<"x"<<imgH;
00128     if (imgW == 0) {
00129         return;
00130     }
00131 
00132     // Draw the tiles and background in the playfield.
00133     if (playfield) {
00134     makeTiles (changePixmaps);
00135 
00136     // Set each cell to same type of tile (i.e. tile-number) as before.
00137     for (int x = 0; x < FIELDWIDTH; x++) {
00138         for (int y = 0; y < FIELDHEIGHT; y++) {
00139         playfield->setTile (x, y, tileNo[x][y]);
00140         }
00141     }
00142     }
00143     kDebug() << t.restart() << "msec.  Tiles and background rendered.";
00144 
00145     /* ******************************************************************** */
00146     /* The pixmaps for hero and enemies are arranged in strips of 36: walk  */
00147     /* right (8), walk left (8), climb right along bar (8), climb left (8), */
00148     /* climb up ladder (2) and fall (2) --- total 36.  The appendFrames()   */
00149     /* method extracts the frames from the strip, scales                    */
00150     /* them and adds them to a list of frames (QPixmaps).                   */
00151     /* ******************************************************************** */
00152 
00153     if (changePixmaps) {
00154     heroFrames->clear();
00155     enemyFrames->clear();
00156 
00157     *heroFrames << theme.hero(imgH);
00158     *enemyFrames << theme.enemy(imgH);
00159     }
00160     kDebug() << t.restart() << "msec.  Hero and enemies rendered.";
00161 
00162     int spriteframe;
00163     QPoint spriteloc;
00164 
00165     // Draw the hero.
00166     if (heroSprite) {
00167         spriteframe = heroSprite->currentFrame();
00168         spriteloc = heroSprite->currentLoc();
00169         heroSprite->addFrames (heroFrames, topLeft, scale);
00170 
00171     // Force a re-draw of both pixmap and position.
00172         heroSprite->move (0, 0, (spriteframe > 0) ? 0 : 1);
00173         heroSprite->move (spriteloc.x(), spriteloc.y(), spriteframe);
00174     }
00175 
00176     if (enemySprites) {
00177     for (int i = 0; i < enemySprites->size(); ++i) {
00178         // kDebug() << "accessing enemySprite" << i;
00179             KGrSprite * thisenemy = enemySprites->at(i);
00180         if (thisenemy) {
00181         spriteframe = thisenemy->currentFrame();
00182             spriteloc = thisenemy->currentLoc();
00183         thisenemy->addFrames (enemyFrames, topLeft, scale);
00184 
00185         // Force re-draw of both pixmap and position.
00186         thisenemy->move (0, 0, (spriteframe > 0) ? 0 : 1);
00187             thisenemy->move (spriteloc.x(), spriteloc.y(), spriteframe);
00188         }
00189     }
00190     }
00191     kDebug() << t.restart() << "msec.  Finish KGrCanvas::drawTheScene";
00192 
00193     // Recreate the border.
00194     makeBorder ();
00195 
00196     // Force the title size and position to be re-calculated.
00197     QString t = title->text();
00198     makeTitle ();
00199     setTitle (t);
00200 }
00201 
00202 bool KGrCanvas::changeTheme (const QString & themeFilepath)
00203 {
00204     t.restart();
00205     kDebug() << 0 << "msec.  New Theme -" << themeFilepath;
00206     bool success = theme.load(themeFilepath);
00207     if (success) {
00208     // Use the border color to fill empty rectangles during partial
00209         // repaints and soften their contrast with the rest of the picture.
00210     setPalette(QPalette(theme.borderColor()));
00211     setAutoFillBackground(true);
00212     }
00213     kDebug() << t.restart() << "msec.  Finish loading new theme.";
00214     if (success && (resizeCount > 0)) { // If startup, do not render or paint.
00215     const bool changePixmaps = true;
00216     drawTheScene (changePixmaps);   // Not startup, so re-draw play-area.
00217     }
00218     return success;
00219 }
00220 
00221 void KGrCanvas::resizeEvent (QResizeEvent * event )
00222 {
00223     resizeCount++;
00224     kDebug()<< "KGrCanvas::resizeEvent:" << resizeCount << event->size();
00225     kDebug() << "Resize pending?" << QWidget::testAttribute (Qt::WA_PendingResizeEvent);
00226     // To reduce overheads, re-render only when no later resize is scheduled.
00227     if (QWidget::testAttribute (Qt::WA_PendingResizeEvent))  {
00228     return;
00229     }
00230 
00231     // When we get here for the first time, the initial SVG theme has been
00232     // loaded, but, to save overheads, it has not been rendered or painted.
00233 
00234     t.start(); // IDW
00235     double w = (double) event->size().width()  / (nCellsW + border);
00236     double h = (double) event->size().height() / (nCellsH + border);
00237     int cellSize = (w < h) ? (int) (w + 0.05) : (int) (h + 0.05);
00238 
00239     imgW = cellSize;
00240     imgH = cellSize;
00241     topLeft.setX ((event->size().width()  - (nCellsW * imgW)) / 2);
00242     topLeft.setY ((event->size().height() - (nCellsH * imgH)) / 2);
00243 
00244     bool changePixmaps = ((imgW != oldImgW) || (imgH != oldImgH));
00245     oldImgW = imgW;
00246     oldImgH = imgH;
00247 
00248     drawTheScene (changePixmaps);
00249     QWidget::resizeEvent (event);
00250 }
00251 
00252 void KGrCanvas::paintCell (int x, int y, char type, int offset)
00253 {
00254     int tileNumber = 0;
00255 
00256     switch (type) {
00257     case FREE:    tileNumber = freebg; break;   // Free space.
00258     case NUGGET:  tileNumber = nuggetbg; break; // Nugget.
00259     case POLE:    tileNumber = polebg; break;   // Pole or bar.
00260     case LADDER:  tileNumber = ladderbg; break; // Ladder.
00261     case HLADDER: tileNumber = hladderbg; break;// Hidden ladder.
00262     case HERO:    tileNumber = edherobg; break; // Static hero (for editing).
00263     case ENEMY:   tileNumber = edenemybg; break;// Static enemy (for editing).
00264     case BETON:   tileNumber = betonbg;  break; // Concrete.
00265     case BRICK:   tileNumber = brickbg;  break; // Solid brick.
00266     case FBRICK:  tileNumber = fbrickbg; break; // False brick.
00267     default:      tileNumber = freebg;  break;
00268     }
00269 
00270     // In KGrGame, the top-left visible cell is [1,1]: in KGrPlayfield [0,0].
00271     x--; y--;
00272     tileNumber = tileNumber + offset;   // Offsets 1-9 are for digging sequence.
00273     tileNo [x][y] = tileNumber;     // Save the tile-number for repaint.
00274 
00275     playfield->setTile (x, y, tileNumber);  // Paint with required pixmap.
00276 }
00277 
00278 void KGrCanvas::setBaseScale ()
00279 {
00280     // Synchronize the desktop font size with the initial canvas scale.
00281     baseScale = scaleStep;
00282     QString t = "";
00283     if (title) {
00284     t = title->text();
00285     }
00286     makeTitle ();
00287     setTitle (t);
00288 }
00289 
00290 void KGrCanvas::setTitle (const QString &newTitle)
00291 {
00292     title->setText (newTitle);
00293 }
00294 
00295 void KGrCanvas::makeTitle ()
00296 {
00297     if (title != 0)
00298     title->close();         // Close and delete previous title.
00299 
00300     title = new QLabel ("", this);
00301     int lw = imgW / lineDivider;    // Line width (as used in makeBorder()).
00302     title->resize (width(), topLeft.y() - lw);
00303     title->move (0, 0);
00304     QPalette palette;
00305     palette.setColor(title->backgroundRole(), theme.borderColor());
00306     palette.setColor(title->foregroundRole(), theme.textColor());
00307     title->setPalette(palette);
00308     title->setFont (QFont (fontInfo().family(),
00309          (baseFontSize * scaleStep) / baseScale, QFont::Bold));
00310     title->setAlignment (Qt::AlignCenter);
00311     title->setAttribute(Qt::WA_QuitOnClose, false); //Otherwise the close above might exit app
00312     title->raise();
00313     title->show();
00314 }
00315 
00316 void KGrCanvas::mousePressEvent ( QMouseEvent * mouseEvent )
00317 {
00318     emit mouseClick(mouseEvent->button());
00319 }
00320 
00321 void KGrCanvas::mouseReleaseEvent ( QMouseEvent * mouseEvent )
00322 {
00323     emit mouseLetGo(mouseEvent->button());
00324 }
00325 
00326 QPoint KGrCanvas::getMousePos ()
00327 {
00328     int i, j;
00329     QPoint p = mapFromGlobal (m->pos());
00330 
00331     // In KGoldrunner, the top-left visible cell is [1,1]: in KGrSprite [0,0].
00332     i = ((p.x() - topLeft.x()) / imgW) + 1;
00333     j = ((p.y() - topLeft.y()) / imgH) + 1;
00334 
00335     return (QPoint (i, j));
00336 }
00337 
00338 void KGrCanvas::setMousePos (int i, int j)
00339 {
00340     // In KGoldrunner, the top-left visible cell is [1,1]: in KGrSprite [0,0].
00341     i--; j--;
00342     m->setPos (mapToGlobal (QPoint (
00343                 topLeft.x() + i * imgW + imgW / 2,
00344                 topLeft.y() + j * imgH + imgH / 2)));
00345 }
00346 
00347 void KGrCanvas::makeHeroSprite (int i, int j, int startFrame)
00348 {
00349     heroSprite = new KGrSprite (this);
00350 
00351     double scale = (double) imgW / (double) bgw;
00352     heroSprite->addFrames (heroFrames, topLeft, scale);
00353 
00354     // In KGoldrunner, the top-left visible cell is [1,1]: in KGrSprite [0,0].
00355     i--; j--;
00356     heroSprite->move (i * bgw, j * bgh, startFrame);
00357     heroSprite->setZ (1);
00358     heroSprite->setVisible (true);
00359 }
00360 
00361 void KGrCanvas::setHeroVisible (bool newState)
00362 {
00363     heroSprite->setVisible (newState);      // Show or hide the hero.
00364 }
00365 
00366 void KGrCanvas::makeEnemySprite (int i, int j, int startFrame)
00367 {
00368     KGrSprite * enemySprite = new KGrSprite (this);
00369 
00370     double scale = (double) imgW / (double) bgw;
00371     enemySprite->addFrames (enemyFrames, topLeft, scale);
00372     enemySprites->append (enemySprite);
00373 
00374     // In KGoldrunner, the top-left visible cell is [1,1]: in KGrSprite [0,0].
00375     i--; j--;
00376     enemySprite->move (i * bgw, j * bgh, startFrame);
00377     enemySprite->setZ (2);
00378     enemySprite->show();
00379 }
00380 
00381 void KGrCanvas::moveHero (int x, int y, int frame)
00382 {
00383     // In KGoldrunner, the top-left visible cell is [1,1]: in KGrSprite [0,0].
00384     heroSprite->move (x - bgw, y - bgh, frame);
00385 }
00386 
00387 void KGrCanvas::moveEnemy (int id, int x, int y, int frame, int nuggets)
00388 {
00389     if (nuggets != 0) {             // If enemy is carrying gold,
00390     frame = frame + goldEnemy;      // show him with gold outline.
00391     }
00392 
00393     // In KGoldrunner, the top-left visible cell is [1,1]: in KGrSprite [0,0].
00394     // kDebug() << "accessing enemySprite" << id;
00395     enemySprites->at(id)->move (x - bgw, y - bgh, frame);
00396 }
00397 
00398 void KGrCanvas::deleteEnemySprites()
00399 {
00400     while (!enemySprites->isEmpty())
00401             delete enemySprites->takeFirst();
00402 }
00403 
00404 QPixmap KGrCanvas::getPixmap (char type)
00405 {
00406     int tileNumber;
00407 
00408     // Get a pixmap from the tile-array for use on an edit-button.
00409     switch (type) {
00410     case FREE:    tileNumber = freebg; break;   // Free space.
00411     case NUGGET:  tileNumber = nuggetbg; break; // Nugget.
00412     case POLE:    tileNumber = polebg; break;   // Pole or bar.
00413     case LADDER:  tileNumber = ladderbg; break; // Ladder.
00414     case HLADDER: tileNumber = hladderbg; break;// Hidden ladder.
00415     case HERO:    tileNumber = edherobg; break; // Static hero (for editing).
00416     case ENEMY:   tileNumber = edenemybg; break;// Static enemy (for editing).
00417     case BETON:   tileNumber = betonbg;  break; // Concrete.
00418     case BRICK:   tileNumber = brickbg;  break; // Solid brick.
00419     case FBRICK:  tileNumber = fbrickbg; break; // False brick.
00420     default:      tileNumber = freebg;  break;
00421     }
00422 
00423     // kDebug() << "accessing tile" << tileNumber;
00424     return tileset->at(tileNumber);
00425 }
00426 
00427 void KGrCanvas::initView()
00428 {
00429     // Set up the pixmaps for the editable objects.
00430     freebg  = 0;        // Free space.
00431     nuggetbg    = 1;        // Nugget.
00432     polebg  = 2;        // Pole or bar.
00433     ladderbg    = 3;        // Ladder.
00434     hladderbg   = 4;        // Hidden ladder.
00435     edherobg    = 5;        // Static hero (for editing).
00436     edenemybg   = 6;        // Static enemy (for editing).
00437     betonbg = 7;        // Concrete.
00438     fbrickbg    = 8;        // False brick.
00439 
00440     // The bricks have 10 pixmaps (showing various stages of digging).
00441     brickbg = 9;        // Solid brick - 1st pixmap.
00442 
00443 
00444     // Set default tile-size (if not played before or no KMainWindow settings).
00445     imgW = (bgw * scaleStep) / STEP;
00446     imgH = (bgh * scaleStep) / STEP;
00447     oldImgW = 0;
00448     oldImgH = 0;
00449 
00450     // Define the canvas as an array of tiles.  Default tile is 0 (free space).
00451     playfield = new KGrPlayField(this); // The drawing-area for the playfield.
00452     tileset     = new QList<QPixmap>(); // The tiles that can be set in there.
00453     heroFrames  = new QList<QPixmap>(); // Animation frames for the hero.
00454     enemyFrames = new QList<QPixmap>(); // Animation frames for enemies.
00455     goldEnemy = 36;         // Offset of gold-carrying frames.
00456 }
00457 
00458 void KGrCanvas::setLevel(unsigned int l)
00459 {
00460     if (l != level) {
00461     level= l;
00462     if (theme.multipleBackgrounds()) {
00463         loadBackground();
00464     }
00465     }
00466 }
00467 
00468 void KGrCanvas::loadBackground()
00469 {
00470     kDebug() << "loadBackground called";
00471     bool fillCanvas = !theme.isBorderRequired(); // Background must fill canvas?
00472     int w = fillCanvas ? (this->width())  : (nCellsW * imgW);
00473     int h = fillCanvas ? (this->height()) : (nCellsH * imgH);
00474     if (theme.isWithBackground()) {
00475     QImage background = theme.background(w, h, level);
00476     playfield->setBackground (true, 
00477         &background, 
00478         theme.isBorderRequired() ? topLeft : QPoint(0, 0));
00479     } else {
00480     playfield->setBackground (true, 
00481         NULL, 
00482         theme.isBorderRequired() ? topLeft : QPoint(0, 0));
00483     }
00484 }
00485 
00486 void KGrCanvas::makeTiles (bool changePixmaps)
00487 {
00488     loadBackground();
00489 
00490     if (changePixmaps) {
00491     tileset->clear();
00492 
00493     *tileset << theme.tiles(imgH);
00494     }
00495 
00496     // Now set our tileset in the scene.
00497     playfield->setTiles (tileset, topLeft, nCellsW, nCellsH, imgW, imgH);
00498 }
00499 
00500 void KGrCanvas::makeBorder ()
00501 {
00502     // Draw main part of border, in the order: top, bottom, left, right.
00503     // Allow some overlap to prevent slits appearing when resizing.
00504 
00505     colour = theme.borderColor();
00506     int cw = width();               // Size of canvas.
00507     int ch = width();
00508     int pw = nCellsW * imgW;            // Size of playfield.
00509     int ph = nCellsH * imgW;
00510     int tlX = topLeft.x();          // Top left of playfield.
00511     int tlY = topLeft.y();
00512     int lw = imgW / lineDivider;        // Line width.
00513 
00514     while (!borderRectangles.isEmpty())
00515             delete borderRectangles.takeFirst();
00516 
00517     KGameCanvasRectangle * nextRectangle;
00518 
00519     // If SVG/PNG background, coloured border is specified in the theme
00520     // properties, otherwise the background fills the canvas.
00521     if (theme.isBorderRequired()) {
00522     nextRectangle = drawRectangle (0, 0, cw, tlY - lw);
00523     borderRectangles.append(nextRectangle);
00524     nextRectangle = drawRectangle (0, tlY + ph + lw,
00525                         cw, ch - tlY - ph - lw);
00526     borderRectangles.append(nextRectangle);
00527     nextRectangle = drawRectangle (0, tlY - lw, tlX - lw, ph + 2*lw);
00528     borderRectangles.append(nextRectangle);
00529     nextRectangle = drawRectangle (tlX + pw + lw, tlY - lw,
00530                         cw - tlX -pw - lw, ph + 2*lw);
00531     borderRectangles.append(nextRectangle);
00532     }
00533 
00534     // Draw the inside edges of the border, in the same way.
00535     colour = QColor (Qt::black);
00536 
00537     nextRectangle = drawRectangle (tlX - lw, tlY - lw, pw + 2*lw, lw);
00538     borderRectangles.append(nextRectangle);
00539     nextRectangle = drawRectangle (tlX - lw, ph + tlY, pw + 2*lw, lw);
00540     borderRectangles.append(nextRectangle);
00541     nextRectangle = drawRectangle (tlX - lw, tlY, lw, ph);
00542     borderRectangles.append(nextRectangle);
00543     nextRectangle = drawRectangle (tlX + pw, tlY, lw, ph);
00544     borderRectangles.append(nextRectangle);
00545 }
00546 
00547 void KGrCanvas::drawSpotLight(qreal value)
00548 {
00549     static int count = 0;
00550     if (value > 0.99) {
00551     count = 0;
00552     // Hide the spotlight animation -- all scene visible
00553     m_spotLight->hide();
00554     m_spotLight->lower();
00555     return;
00556     }
00557     count++;
00558     m_spotLight->raise();
00559     m_spotLight->show();
00560     QPicture picture;
00561     qreal w = qreal(nCellsW * imgW);
00562     qreal h = qreal(nCellsH * imgW);
00563     qreal x = qreal(topLeft.x());
00564     qreal y = qreal(topLeft.y());
00565     qreal dh = 0.5 * ::sqrt(w * w + h * h);
00566 
00567     QPainter p(&picture);
00568     if (value < 0.01) {
00569     // Draw a solid black background if the circle would be too small/
00570     p.fillRect(QRectF(x, y, w, h), QColor(0, 0, 0, 255));
00571     } else {
00572     static const qreal outerRatio = 1.00;
00573     static const qreal innerRatio = 0.85;
00574     static const qreal sqrt1_2 = 0.5 * ::sqrt(2);
00575     qreal wh = w * 0.5;
00576     qreal hh = h * 0.5;
00577     qreal radius = dh * value;
00578     qreal innerRadius = radius * innerRatio;
00579     qreal innerDistance = sqrt1_2 * innerRadius;
00580     qreal side = 2.0 * innerDistance;
00581 
00582     QPointF center(width() * 0.5, height() * 0.5);
00583     QRadialGradient gradient(center, radius, center);
00584     gradient.setColorAt(outerRatio, QColor(0, 0, 0, 255));
00585     gradient.setColorAt(innerRatio, QColor(0, 0, 0, 0));
00586 
00587     QBrush brush(gradient);
00588         QBrush blackbrush(QColor(0, 0, 0, 255));
00589     // Draw a transparent circle over the scene.
00590     p.setCompositionMode(QPainter::CompositionMode_SourceOver);
00591     if (radius < wh) {
00592         // If the spotlight radius is smaller than half the scene width,
00593         // draw black rectangles to its sides, which is faster.
00594         qreal diameter = radius * 2.0;
00595         p.fillRect(QRectF(x, y, 1.0 + wh - radius, h), blackbrush);
00596         p.fillRect(QRectF(x + wh + radius, y, wh - radius, h), blackbrush);
00597         if (radius < hh) {
00598         // If the spotlight radius is smaller than half the scene
00599         // height, draw black rectangles to its top and bottom sides,
00600         // which is faster.
00601         p.fillRect(QRectF(x + wh - radius, y, diameter, hh - radius + 1.0), blackbrush);
00602         p.fillRect(QRectF(x + wh - radius, y + hh + radius, diameter, hh - radius), blackbrush);
00603         
00604         // Draw the spotlight circle, but skip the transparent center.
00605         p.fillRect(QRectF(x + wh - radius, y + hh - radius, radius - innerDistance, diameter), brush);
00606         p.fillRect(QRectF(x + wh + innerDistance, y + hh - radius, radius - innerDistance, diameter), brush);
00607         p.fillRect(QRectF(x + wh - innerDistance, y + hh - radius, side, radius - innerDistance), brush);
00608         p.fillRect(QRectF(x + wh - innerDistance, y + hh + innerDistance, side, radius - innerDistance), brush);
00609         } else {
00610         // Else draw the radial gradient
00611         p.fillRect(QRectF(x + wh - radius, y, diameter, h), brush);
00612         }
00613     } else {
00614         // If the spotlight is bigger than the scene, draw only the
00615         // sections where the gradient is not transparent.
00616         p.fillRect(QRectF(x, y, wh - innerDistance, h), brush);
00617         p.fillRect(QRectF(x + wh + innerDistance, y, wh - innerDistance, h), brush);
00618         if (innerDistance < hh) {
00619         p.fillRect(QRectF(x + wh - innerDistance, y, side, hh - innerDistance), brush);
00620         p.fillRect(QRectF(x + wh - innerDistance, y + hh + innerDistance, side, hh - innerDistance), brush);
00621         }
00622     }
00623     }
00624 
00625     p.end();
00626     m_spotLight->setPicture(picture);
00627 }
00628 
00629 KGameCanvasRectangle * KGrCanvas::drawRectangle (int x, int y, int w, int h)
00630 {
00631     KGameCanvasRectangle * r =
00632         new KGameCanvasRectangle (colour, QSize(w, h), this);
00633     r->moveTo (x, y);
00634     r->show();
00635     return (r);
00636 }
00637 
00638 QSize KGrCanvas::sizeHint() const
00639 {
00640     return QSize ((nCellsW  + border) * imgW, (nCellsH + border) * imgH);
00641 }
00642 
00643 #include "kgrcanvas.moc"

kgoldrunner

Skip menu "kgoldrunner"
  • Main Page
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Class Members

API Reference

Skip menu "API Reference"
  • kblackbox
  • kgoldrunner
  • kmahjongg
  • ksquares
  • libkdegames
  •   highscore
  •   kgame
  •   kggzgames
  •   kggzmod
  •   kggznet
  • libkmahjongg
Generated for API Reference by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal