File indexing completed on 2024-10-13 03:43:42
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"