00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
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;
00039
00040 kDebug() << "Called KGrCanvas::KGrCanvas ..." << this->size();
00041 m = new QCursor ();
00042
00043
00044 setPalette(QPalette(Qt::black));
00045 setAutoFillBackground(true);
00046
00047 scaleStep = STEP;
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;
00056 lineDivider = 8;
00057
00058 heroSprite = 0;
00059
00060
00061 enemySprites = new QList<KGrSprite *> ();
00062
00063 kDebug() << "Calling initView() ...";
00064 initView();
00065
00066
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
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
00120
00121
00122
00123
00124
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
00133 if (playfield) {
00134 makeTiles (changePixmaps);
00135
00136
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
00147
00148
00149
00150
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
00166 if (heroSprite) {
00167 spriteframe = heroSprite->currentFrame();
00168 spriteloc = heroSprite->currentLoc();
00169 heroSprite->addFrames (heroFrames, topLeft, scale);
00170
00171
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
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
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
00194 makeBorder ();
00195
00196
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
00209
00210 setPalette(QPalette(theme.borderColor()));
00211 setAutoFillBackground(true);
00212 }
00213 kDebug() << t.restart() << "msec. Finish loading new theme.";
00214 if (success && (resizeCount > 0)) {
00215 const bool changePixmaps = true;
00216 drawTheScene (changePixmaps);
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
00227 if (QWidget::testAttribute (Qt::WA_PendingResizeEvent)) {
00228 return;
00229 }
00230
00231
00232
00233
00234 t.start();
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;
00258 case NUGGET: tileNumber = nuggetbg; break;
00259 case POLE: tileNumber = polebg; break;
00260 case LADDER: tileNumber = ladderbg; break;
00261 case HLADDER: tileNumber = hladderbg; break;
00262 case HERO: tileNumber = edherobg; break;
00263 case ENEMY: tileNumber = edenemybg; break;
00264 case BETON: tileNumber = betonbg; break;
00265 case BRICK: tileNumber = brickbg; break;
00266 case FBRICK: tileNumber = fbrickbg; break;
00267 default: tileNumber = freebg; break;
00268 }
00269
00270
00271 x--; y--;
00272 tileNumber = tileNumber + offset;
00273 tileNo [x][y] = tileNumber;
00274
00275 playfield->setTile (x, y, tileNumber);
00276 }
00277
00278 void KGrCanvas::setBaseScale ()
00279 {
00280
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();
00299
00300 title = new QLabel ("", this);
00301 int lw = imgW / lineDivider;
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);
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
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
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
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);
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
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
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) {
00390 frame = frame + goldEnemy;
00391 }
00392
00393
00394
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
00409 switch (type) {
00410 case FREE: tileNumber = freebg; break;
00411 case NUGGET: tileNumber = nuggetbg; break;
00412 case POLE: tileNumber = polebg; break;
00413 case LADDER: tileNumber = ladderbg; break;
00414 case HLADDER: tileNumber = hladderbg; break;
00415 case HERO: tileNumber = edherobg; break;
00416 case ENEMY: tileNumber = edenemybg; break;
00417 case BETON: tileNumber = betonbg; break;
00418 case BRICK: tileNumber = brickbg; break;
00419 case FBRICK: tileNumber = fbrickbg; break;
00420 default: tileNumber = freebg; break;
00421 }
00422
00423
00424 return tileset->at(tileNumber);
00425 }
00426
00427 void KGrCanvas::initView()
00428 {
00429
00430 freebg = 0;
00431 nuggetbg = 1;
00432 polebg = 2;
00433 ladderbg = 3;
00434 hladderbg = 4;
00435 edherobg = 5;
00436 edenemybg = 6;
00437 betonbg = 7;
00438 fbrickbg = 8;
00439
00440
00441 brickbg = 9;
00442
00443
00444
00445 imgW = (bgw * scaleStep) / STEP;
00446 imgH = (bgh * scaleStep) / STEP;
00447 oldImgW = 0;
00448 oldImgH = 0;
00449
00450
00451 playfield = new KGrPlayField(this);
00452 tileset = new QList<QPixmap>();
00453 heroFrames = new QList<QPixmap>();
00454 enemyFrames = new QList<QPixmap>();
00455 goldEnemy = 36;
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();
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
00497 playfield->setTiles (tileset, topLeft, nCellsW, nCellsH, imgW, imgH);
00498 }
00499
00500 void KGrCanvas::makeBorder ()
00501 {
00502
00503
00504
00505 colour = theme.borderColor();
00506 int cw = width();
00507 int ch = width();
00508 int pw = nCellsW * imgW;
00509 int ph = nCellsH * imgW;
00510 int tlX = topLeft.x();
00511 int tlY = topLeft.y();
00512 int lw = imgW / lineDivider;
00513
00514 while (!borderRectangles.isEmpty())
00515 delete borderRectangles.takeFirst();
00516
00517 KGameCanvasRectangle * nextRectangle;
00518
00519
00520
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
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
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
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
00590 p.setCompositionMode(QPainter::CompositionMode_SourceOver);
00591 if (radius < wh) {
00592
00593
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
00599
00600
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
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
00611 p.fillRect(QRectF(x + wh - radius, y, diameter, h), brush);
00612 }
00613 } else {
00614
00615
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"