File indexing completed on 2024-04-28 04:02:15

0001 /*
0002     SPDX-FileCopyrightText: 2012 Roney Gomes <roney477@gmail.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include <KLocalizedString>
0008 
0009 #include <QFont>
0010 #include <QTimeLine>
0011 
0012 #include "kgoldrunner_debug.h"
0013 #include "kgrview.h"
0014 #include "kgrscene.h"
0015 #include "kgrsprite.h"
0016 #include "kgrrenderer.h"
0017 
0018 const StartFrame animationStartFrames [nAnimationTypes] = {
0019                  RIGHTWALK1,    LEFTWALK1,  RIGHTCLIMB1,    LEFTCLIMB1,
0020                  CLIMB1,        CLIMB1,     FALL1,          FALL2,
0021                  DIGBRICK1, // Start frame for OPEN_BRICK.
0022                  DIGBRICK6};    // Start frame for CLOSE_BRICK.
0023 
0024 KGrScene::KGrScene      (KGrView * view)
0025     :
0026     QGraphicsScene      (view),
0027     // Allow FIELDWIDTH * FIELDHEIGHT tiles for the KGoldruner level-layouts,
0028     // plus 2 more tile widths all around for text areas, frame and spillover
0029     // for mouse actions (to avoid accidental clicks affecting the desktop).
0030     m_view              (view),
0031     m_background        (nullptr),
0032     m_level             (1),
0033     m_title             (nullptr),
0034     m_replayMessage     (nullptr),
0035     m_livesText         (nullptr),
0036     m_scoreText         (nullptr),
0037     m_hasHintText       (nullptr),
0038     m_pauseResumeText   (nullptr),
0039     m_heroId            (0),
0040     m_tilesWide         (FIELDWIDTH  + 2 * 2),
0041     m_tilesHigh         (FIELDHEIGHT + 2 * 2),
0042     m_tileSize          (10),
0043     m_toolbarTileSize   (10),
0044     m_themeChanged      (true),
0045     m_topLeftX          (0),
0046     m_topLeftY          (0),
0047     m_mouse             (new QCursor()),
0048     m_fadingTimeLine    (new QTimeLine (1000, this))
0049 {
0050     setItemIndexMethod(NoIndex);
0051 
0052     m_tiles.fill        (nullptr,     m_tilesWide * m_tilesHigh);
0053     m_tileTypes.fill    (FREE,  m_tilesWide * m_tilesHigh);
0054 
0055     m_renderer  = new KGrRenderer (this);
0056 
0057     m_frame = addRect (0, 0, 100, 100);     // Create placeholder for frame.
0058     m_frame->setVisible (false);
0059 
0060     m_spotlight = addRect (0, 0, 100, 100); // Create placeholder for spot.
0061     m_spotlight->setVisible (false);
0062 
0063     m_title = new QGraphicsSimpleTextItem();
0064     addItem (m_title);
0065 
0066     m_replayMessage = new QGraphicsSimpleTextItem();
0067     addItem (m_replayMessage);
0068     m_replayMessage->setVisible (false);    // Visible only in demo/replay.
0069 
0070     m_livesText = new QGraphicsSimpleTextItem();
0071     addItem (m_livesText);
0072 
0073     m_scoreText = new QGraphicsSimpleTextItem();
0074     addItem (m_scoreText);
0075 
0076     m_hasHintText = new QGraphicsSimpleTextItem();
0077     addItem (m_hasHintText);
0078 
0079     m_pauseResumeText = new QGraphicsSimpleTextItem();
0080     addItem (m_pauseResumeText);
0081 
0082     m_fadingTimeLine->setEasingCurve(QEasingCurve::OutCurve);
0083     m_fadingTimeLine->setUpdateInterval (50);
0084     connect(m_fadingTimeLine, &QTimeLine::valueChanged, this, &KGrScene::drawSpotlight);
0085     connect(m_fadingTimeLine, &QTimeLine::finished, this, &KGrScene::fadeFinished);
0086 }
0087 
0088 KGrScene::~KGrScene()
0089 {
0090     delete m_mouse;
0091     delete m_fadingTimeLine;
0092 }
0093 
0094 void KGrScene::redrawScene ()
0095 {
0096     //qCDebug(KGOLDRUNNER_LOG) << "REDRAW: m_sizeChanged" << m_sizeChanged << "m_themeChanged" << m_themeChanged;
0097     bool redrawToolbar = false;
0098     if (m_sizeChanged) {
0099         // Calculate what size of tile will fit in the view.
0100         QSize size      = m_view->size();
0101         int tileSize    = qMin (size.width()  / m_tilesWide,
0102                                 size.height() / m_tilesHigh);
0103         m_topLeftX   = (size.width()  - m_tilesWide * tileSize)/2.0;
0104         m_topLeftY   = (size.height() - m_tilesHigh * tileSize)/2.0;
0105         setSceneRect   (0, 0, size.width(), size.height());
0106     //qCDebug(KGOLDRUNNER_LOG) << "SIZE" << size << "TL" << m_topLeftX << m_topLeftY << "TILE" << tileSize << "was" << m_tileSize << m_toolbarTileSize;
0107 
0108         // Make the fade-out/fade-in rectangle cover the playing area.
0109         m_spotlight->setRect (m_topLeftX + 2 * tileSize - 1,
0110                               m_topLeftY + 2 * tileSize - 1,
0111                               (m_tilesWide - 4) * tileSize + 2,
0112                               (m_tilesHigh - 4) * tileSize + 2);
0113         m_maxRadius = (5 * m_spotlight->rect().width() + 4) / 8;
0114         m_spotlight->setPen (Qt::NoPen);
0115         m_spotlight->setZValue (10);
0116         m_spotlight->setVisible (false);
0117 
0118         // Set up the gradient to draw the spotlight (black with a hole in it).
0119         QPointF center        (width() * 0.5, height() * 0.5);
0120         m_gradient.setCenter  (center);
0121         m_gradient.setFocalPoint (center);
0122         m_gradient.setRadius  (m_maxRadius);
0123         m_gradient.setColorAt (1.00, QColor (0, 0, 0, 255));
0124         m_gradient.setColorAt (0.85, QColor (0, 0, 0, 0));
0125 
0126         int index = 0;
0127         for (KGameRenderedItem * tile : std::as_const(m_tiles)) {
0128             if (tile) {
0129                 setTile (tile, tileSize, index/m_tilesHigh, index%m_tilesHigh);
0130             }
0131             index++;
0132         }
0133         for (KGrSprite * sprite : std::as_const(m_sprites)) {
0134             if (sprite) {
0135                 sprite->changeCoordinateSystem
0136                         (m_topLeftX, m_topLeftY, tileSize);
0137             }
0138         }
0139 
0140         if (m_tileSize != tileSize) {
0141             // Do not expand the toolbar (in edit mode) until there is room for
0142             // it.  This avoids a nasty expand-contract-expand-contract loop.
0143             m_toolbarTileSize = ((tileSize > m_tileSize) && (m_topLeftY == 0)) ?
0144                                   m_tileSize : tileSize;
0145         }
0146         // When conditions are right, redraw editing icons, if in edit mode.
0147         redrawToolbar = ((m_toolbarTileSize != m_tileSize) &&
0148                          (m_topLeftY > 0)) ? true : false;
0149         m_tileSize = tileSize;
0150         m_sizeChanged = false;
0151     }
0152 
0153     // Re-draw text, background and frame if either scene-size or theme changes.
0154 
0155     // Resize and draw texts for title, score, lives, hasHint and pauseResume.
0156     setTextFont (m_title, 0.6);
0157     setTitle (m_title->text());
0158     placeTextItems();
0159 
0160     // Resize and draw different backgrounds, depending on the level and theme.
0161     loadBackground (m_level);
0162 
0163     if (m_renderer->hasBorder()) {
0164         // There are border tiles in the theme, so do not draw a frame.
0165         m_frame->setVisible (false);
0166     }
0167     else {
0168         // There are no border tiles, so draw a frame around the board.
0169         drawFrame();
0170     }
0171 
0172     if (m_themeChanged) {
0173         // Fill the scene (and view) with the new background color.  Do this
0174         // even if the background has no border, to avoid ugly white rectangles
0175         // appearing if rendering and painting is momentarily a bit slow.
0176         setBackgroundBrush (m_renderer->borderColor());
0177 
0178     // Erase border tiles (if any) and draw new ones, if new theme has them.
0179         drawBorder();
0180 
0181         // Redraw all the tiles, except for borders and tiles of type FREE.
0182         for (int i = 1; i <= FIELDWIDTH; i++) {
0183             for (int j = 1; j <= FIELDHEIGHT; j++) {
0184                 int index = i * m_tilesHigh + j;
0185                 paintCell (i, j, m_tileTypes[index]);
0186             }
0187         }
0188 
0189         // Redraw editing icons if theme changes when in edit mode.
0190         redrawToolbar = true;
0191         m_themeChanged = false;
0192     }
0193 
0194     if (redrawToolbar) {
0195         m_toolbarTileSize = m_tileSize; // If game is in edit mode, KGoldrunner
0196         Q_EMIT redrawEditToolbar(); // object redraws the editToolbar.
0197     }
0198 }
0199 
0200 void KGrScene::changeTheme()
0201 {
0202     m_themeChanged = true;
0203     redrawScene();
0204 }
0205 
0206 void KGrScene::changeSize()
0207 {
0208     m_sizeChanged = true;
0209     redrawScene();
0210 }
0211 
0212 void KGrScene::setTitle (const QString & newTitle)
0213 {
0214     if (! m_title) return;
0215 
0216     m_title->setText (newTitle);
0217     QRectF r = m_title->boundingRect();     // Centre the title.
0218     m_title->setPos ((sceneRect().width() - r.width())/2,
0219                       m_topLeftY + (m_tileSize - r.height())/2);
0220 }
0221 
0222 void KGrScene::setReplayMessage (const QString & msg)
0223 {
0224     m_replayMessage->setText (msg);
0225 }
0226 
0227 void KGrScene::showReplayMessage (bool onOff)
0228 {
0229     m_replayMessage->setVisible (onOff);
0230 }
0231 
0232 void KGrScene::placeTextItems()
0233 {
0234     setTextFont (m_replayMessage, 0.5);
0235     setTextFont (m_livesText, 0.5);
0236     setTextFont (m_scoreText, 0.5);
0237     setTextFont (m_hasHintText, 0.5);
0238     setTextFont (m_pauseResumeText, 0.5);
0239 
0240     QRectF r = m_replayMessage->boundingRect();
0241     m_replayMessage->setPos ((sceneRect().width() - r.width())/2,
0242                               m_topLeftY + 1.4 * m_tileSize - 0.5 * r.height());
0243     m_replayMessage->setZValue (10);
0244 
0245     qreal totalWidth = 0.0;
0246     r = m_livesText->boundingRect();
0247     qreal x = m_topLeftX + 2 * m_tileSize;
0248     qreal y = sceneRect().height() - m_topLeftY - (m_tileSize + r.height())/2;
0249 
0250     m_livesText->setPos (x, y);
0251     totalWidth += r.width();
0252 
0253     r = m_scoreText->boundingRect();
0254     m_scoreText->setPos (x + totalWidth, y);
0255     totalWidth += r.width();
0256 
0257     r = m_hasHintText->boundingRect();
0258     m_hasHintText->setPos (x + totalWidth, y);
0259     totalWidth += r.width();
0260 
0261     r = m_pauseResumeText->boundingRect();
0262     m_pauseResumeText->setPos (x + totalWidth, y);
0263     totalWidth += r.width();
0264 
0265     qreal spacing = ((m_tilesWide - 4) * m_tileSize - totalWidth) / 3.0;
0266     if (spacing < 0.0)
0267         return;
0268 
0269     m_scoreText->moveBy (spacing, 0.0);
0270     m_hasHintText->moveBy (2.0 * spacing, 0.0);
0271     m_pauseResumeText->moveBy (3.0 * spacing, 0.0);
0272 }
0273 
0274 void KGrScene::showLives (long lives)
0275 {
0276     if (m_livesText)
0277         m_livesText->setText (i18n("Lives: %1", QString::number(lives)
0278                                                 .rightJustified(3, QLatin1Char('0'))));
0279 }
0280 
0281 void KGrScene::showScore (long score)
0282 {
0283     if (m_scoreText)
0284         m_scoreText->setText (i18n("Score: %1", QString::number(score)
0285                                                 .rightJustified(7, QLatin1Char('0'))));
0286 }
0287 
0288 void KGrScene::setHasHintText (const QString & msg)
0289 {
0290     if (m_hasHintText)
0291         m_hasHintText->setText (msg);
0292 }
0293 
0294 void KGrScene::setPauseResumeText (const QString & msg)
0295 {
0296     if (m_pauseResumeText)
0297         m_pauseResumeText->setText (msg);
0298 }
0299 
0300 void KGrScene::goToBlack()
0301 {
0302         drawSpotlight (0);
0303 }
0304 
0305 void KGrScene::fadeIn (bool inOut)
0306 {
0307     // For fade-in,  inOut = true,  circle opens,  from 0.0 to 1.0.
0308     // For fade-out, inOut = false, circle closes, from 1.0 to 0.0.
0309     m_fadingTimeLine->setDirection (inOut ? QTimeLine::Forward
0310                                          : QTimeLine::Backward);
0311     m_fadingTimeLine->start();
0312 }
0313 
0314 void KGrScene::drawSpotlight (qreal ratio)
0315 {
0316     if (ratio > 0.99) {
0317     m_spotlight->setVisible (false);    // End of the close-open cycle.
0318     return;
0319     }
0320     else if (ratio <= 0.01) {
0321     m_spotlight->setBrush (Qt::black);
0322     }
0323     else {
0324         m_gradient.setRadius (ratio * m_maxRadius);
0325         m_spotlight->setBrush (QBrush (m_gradient));
0326     }
0327 
0328     m_spotlight->setVisible (true);
0329 }
0330 
0331 void KGrScene::setLevel (unsigned int level)
0332 {
0333     if (level == m_level) {
0334         return;
0335     }
0336     m_level = level;
0337     loadBackground (level); // Load background for level.
0338 }
0339 
0340 void KGrScene::loadBackground (const int level)
0341 {
0342     // NOTE: The background picture can be the same size as the level-layout (as
0343     // in the Egypt theme) OR it can be the same size as the entire viewport.
0344     // In this example the background is fitted into the level-layout.
0345     m_background = m_renderer->getBackground (level, m_background);
0346 
0347     m_background->setRenderSize (QSize ((m_tilesWide - 4) * m_tileSize,
0348                                         (m_tilesHigh - 4) * m_tileSize));
0349     m_background->setPos    (m_topLeftX + 2 * m_tileSize,
0350                              m_topLeftY + 2 * m_tileSize);
0351     // Keep the background behind the level layout.
0352     m_background->setZValue (-1);
0353 }
0354 
0355 void KGrScene::setTile (KGameRenderedItem * tile, const int tileSize,
0356                         const int i, const int j)
0357 {
0358     tile->setRenderSize (QSize (tileSize, tileSize));
0359     tile->setPos (m_topLeftX + (i+1) * tileSize, m_topLeftY + (j+1) * tileSize);
0360 }
0361 
0362 void KGrScene::setBorderTile (const QString &spriteKey, const int x, const int y)
0363 {
0364     int index               = x * m_tilesHigh + y;
0365     KGameRenderedItem * t   = m_renderer->getBorderItem (spriteKey,
0366                                                          m_tiles.at(index));
0367     m_tiles[index]          = t;
0368 
0369     if (t) {
0370         setTile (t, m_tileSize, x, y);
0371     }
0372 }
0373 
0374 void KGrScene::drawBorder()
0375 {
0376     // Corners.
0377     setBorderTile (QStringLiteral("frame-topleft"), 0, 0);
0378     setBorderTile (QStringLiteral("frame-topright"), FIELDWIDTH + 1, 0);
0379     setBorderTile (QStringLiteral("frame-bottomleft"), 0, FIELDHEIGHT + 1);
0380     setBorderTile (QStringLiteral("frame-bottomright"), FIELDWIDTH + 1, FIELDHEIGHT + 1);
0381 
0382     // Upper side.
0383     for (int i = 1; i <= FIELDWIDTH; i++)
0384         setBorderTile (QStringLiteral("frame-top"), i, 0);
0385 
0386     // Lower side.
0387     for (int i = 1; i <= FIELDWIDTH; i++)
0388         setBorderTile (QStringLiteral("frame-bottom"), i, FIELDHEIGHT + 1);
0389 
0390     // Left side.
0391     for (int i = 1; i <= FIELDHEIGHT; i++)
0392         setBorderTile (QStringLiteral("frame-left"), 0, i);
0393 
0394     // Right side.
0395     for (int i = 1; i <= FIELDHEIGHT; i++)
0396         setBorderTile (QStringLiteral("frame-right"), FIELDWIDTH + 1, i);
0397 }
0398 
0399 void KGrScene::drawFrame()
0400 {
0401     int w = 0.05 * m_tileSize + 0.5;
0402     w = w < 1 ? 1 : w;
0403     m_frame->setRect (
0404     m_topLeftX + (2 * m_tileSize) - (3 * w),
0405     m_topLeftY + (2 * m_tileSize) - (3 * w),
0406     FIELDWIDTH  * m_tileSize + 6 * w,
0407     FIELDHEIGHT * m_tileSize + 6 * w);
0408     //qCDebug(KGOLDRUNNER_LOG) << "FRAME WIDTH" << w << "tile size" << m_tileSize << "rectangle" << m_frame->rect();
0409     QPen pen = QPen (m_renderer->textColor());
0410     pen.setWidth (w);
0411     m_frame->setPen (pen);
0412     m_frame->setVisible (true);
0413 }
0414 
0415 void KGrScene::paintCell (const int i, const int j, const char type)
0416 {
0417     int index               = i * m_tilesHigh + j;
0418     KGameRenderedItem * t   = m_renderer->getTileItem (type, m_tiles.at(index));
0419     m_tiles[index]          = t;
0420     m_tileTypes[index]      = type;
0421 
0422     if (t) {
0423         setTile (t, m_tileSize, i, j);
0424     }
0425 }
0426 
0427 int KGrScene::makeSprite (const char type, int i, int j)
0428 {
0429     int spriteId;
0430     KGrSprite * sprite = m_renderer->getSpriteItem (type, TickTime);
0431 
0432     if (m_sprites.count(nullptr) > 0 &&
0433         ((spriteId = m_sprites.lastIndexOf (nullptr)) >= 0)) {
0434         // Re-use a slot previously occupied by a transient member of the list.
0435         m_sprites[spriteId] = sprite;
0436     }
0437     else {
0438         // Otherwise, add to the end of the list.
0439         spriteId = m_sprites.count();
0440         m_sprites.append (sprite);
0441     }
0442 
0443     int frame1 = animationStartFrames [FALL_L];
0444 
0445     switch (type) {
0446     case HERO:
0447         m_heroId = spriteId;
0448         sprite->setZ (1);
0449         break;
0450     case ENEMY:
0451         sprite->setZ (2);
0452         break;
0453     case BRICK:
0454         frame1 = animationStartFrames [OPEN_BRICK];
0455 
0456         // The hero and enemies must be painted in front of dug bricks.
0457         sprite->setZ (0);
0458 
0459         // Erase the brick-image so that animations are visible in all themes.
0460         paintCell (i, j, FREE);
0461         break;
0462     default:
0463         break;
0464     }
0465 
0466     sprite->setFrame (frame1);
0467     sprite->setCoordinateSystem (m_topLeftX, m_topLeftY, m_tileSize);
0468     addItem (sprite);       // The sprite can be correctly rendered now.
0469     sprite->move (i, j, frame1);
0470     return spriteId;
0471 }
0472 
0473 void KGrScene::animate (bool missed)
0474 {
0475     for (KGrSprite * sprite : std::as_const(m_sprites)) {
0476         if (sprite != nullptr) {
0477             sprite->animate (missed);
0478         }
0479     }
0480 }
0481 
0482 void KGrScene::startAnimation (const int id, const bool repeating,
0483                                 const int i, const int j, const int time,
0484                                 const Direction dirn, const AnimationType type)
0485 {
0486     // TODO - Put most of this in helper code, based on theme parameters.
0487     int dx              = 0;
0488     int dy              = 0;
0489     int frame           = animationStartFrames [type];
0490     int nFrames         = 8;
0491     int nFrameChanges   = 4;
0492 
0493     switch (dirn) {
0494     case RIGHT:
0495         dx    = +1;
0496         break;
0497     case LEFT:
0498         dx    = -1;
0499         break;
0500     case DOWN:
0501         dy = +1;
0502         if ((type == FALL_R) || (type == FALL_L)) {
0503             nFrames = 1;
0504         }
0505         else {
0506             nFrames = 2;
0507         }
0508         break;
0509     case UP:
0510         dy = -1;
0511         nFrames = 2;
0512         break;
0513     case STAND:
0514         switch (type) {
0515         case OPEN_BRICK:
0516             nFrames = 5;
0517             break;
0518         case CLOSE_BRICK:
0519             nFrames = 4;
0520             break;
0521         default:
0522             // Show a standing hero or enemy, using the previous StartFrame.
0523             nFrames = 0; 
0524             break;
0525         }
0526         break;
0527     default:
0528         break;
0529     }
0530 
0531     // TODO - Generalise nFrameChanges = 4, also the tick time = 20 new sprite.
0532     m_sprites.at(id)->setAnimation (repeating, i, j, frame, nFrames, dx, dy,
0533                                     time, nFrameChanges);
0534 }
0535 
0536 void KGrScene::gotGold (const int spriteId, const int i, const int j,
0537                         const bool spriteHasGold, const bool lost)
0538 {
0539     // Hide collected gold or show dropped gold, but not if the gold was lost.
0540     if (! lost) {
0541         paintCell (i, j, (spriteHasGold) ? FREE : NUGGET);
0542     }
0543 
0544     // If the rules allow, show whether or not an enemy sprite is carrying gold.
0545     if (enemiesShowGold && (m_sprites.at(spriteId)->spriteType() == ENEMY)) {
0546         m_sprites.at(spriteId)->setSpriteKey (spriteHasGold ? QStringLiteral("gold_enemy")
0547                                                             : QStringLiteral("enemy"));
0548     }
0549 }
0550 
0551 void KGrScene::showHiddenLadders (const QList<int> & ladders, const int width)
0552 {
0553     for (const int &offset : ladders) {
0554         int i = offset % width;
0555         int j = offset / width;
0556         paintCell (i, j, LADDER);
0557     }
0558 }
0559 
0560 void KGrScene::deleteSprite (const int spriteId)
0561 {
0562     QPointF loc     = m_sprites.at(spriteId)->currentLoc();
0563     bool   brick    = (m_sprites.at(spriteId)->spriteType() == BRICK);
0564 
0565     delete m_sprites.at(spriteId);
0566     m_sprites [spriteId] = nullptr;
0567 
0568     if (brick) {
0569         // Dug-brick sprite erased: restore the tile that was at that location.
0570         paintCell (loc.x(), loc.y(), BRICK);
0571     }
0572 }
0573 
0574 void KGrScene::deleteAllSprites()
0575 {
0576     qDeleteAll(m_sprites);
0577     m_sprites.clear();
0578 }
0579 
0580 void KGrScene::preRenderSprites()
0581 {
0582     char type[2] = {HERO, ENEMY};
0583     for (int t = 0; t < 2; t++) {
0584         KGrSprite * sprite = m_renderer->getSpriteItem (type[t], TickTime);
0585         sprite->setFrame (1);
0586         sprite->setRenderSize (QSize (m_tileSize, m_tileSize));
0587         int count = sprite->frameCount();
0588 
0589         // Pre-render all frames of the hero and an enemy, to avoid hiccups in
0590         // animation during the first few seconds of KGoldrunner execution.
0591         for (int n = 1; n <= count; n++) {
0592             sprite->setFrame (n);
0593         }
0594         delete sprite;
0595     }
0596 }
0597 
0598 void KGrScene::setMousePos (const int i, const int j)
0599 {
0600     m_mouse->setPos (m_view->mapToGlobal (QPoint (
0601                      m_topLeftX + (i + 1) * m_tileSize + m_tileSize/2,
0602                      m_topLeftY + (j + 1) * m_tileSize + m_tileSize/2)));
0603 }
0604 
0605 void KGrScene::getMousePos (int & i, int & j)
0606 {
0607     QPoint pos = m_view->mapFromGlobal (m_mouse->pos());
0608     i = pos.x();
0609     j = pos.y();
0610     if (! m_view->isActiveWindow()) {
0611         i = -2;
0612     j = -2;
0613     return;
0614     }
0615     // IDW TODO - Check for being outside scene. Use saved m_width and m_height.
0616 
0617     i = (i - m_topLeftX)/m_tileSize - 1;
0618     j = (j - m_topLeftY)/m_tileSize - 1;
0619 
0620     // Make sure i and j are within the KGoldrunner playing area.
0621     i = (i < 1) ? 1 : ((i > FIELDWIDTH)  ? FIELDWIDTH  : i);
0622     j = (j < 1) ? 1 : ((j > FIELDHEIGHT) ? FIELDHEIGHT : j);
0623 }
0624 
0625 void KGrScene::setTextFont (QGraphicsSimpleTextItem * t, double fontFraction)
0626 {
0627     QFont f;
0628     f.setPixelSize ((int) (m_tileSize * fontFraction + 0.5));
0629     f.setWeight (QFont::Bold);
0630     f.setStretch (QFont::Expanded);
0631     t->setBrush (m_renderer->textColor());
0632     t->setFont (f);
0633 }
0634 
0635 #include "moc_kgrscene.cpp"