I found another bug in the puzzle: double (or triple) clicking on a piece could make it stop halfway between places and mess up the whole puzzle layout until you resized it. So here's yet another update to the patch to fix that. I also changed the animation from SlideInMovement to FastSlideInMovement in after some changes to Plasma::Animator slowed it down a bit.
Index: fifteen.cpp =================================================================== --- fifteen.cpp (revision 860979) +++ fifteen.cpp (working copy) @@ -26,13 +26,10 @@ #include <QGraphicsSceneMouseEvent> #include <QPainter> -#include <KSvgRenderer> #include <KDebug> #include "plasma/animator.h" -static const int SIZE = 48; - Fifteen::Fifteen(QGraphicsItem *parent) : QGraphicsWidget(parent) { @@ -41,9 +38,24 @@ m_splitPixmap = false; m_numerals = true; + m_svg = new Plasma::Svg(); + m_svg->setImagePath(QLatin1String(":/images/greensquare.svgz")); + shuffle(); } +Fifteen::~Fifteen() +{ + clearPieces(); + delete m_svg; +} + +void Fifteen::updateGraphics() +{ + updatePixmaps(); + drawPieces(); +} + void Fifteen::clearPieces() { for (int i = 0; i < 16; ++i) @@ -74,9 +86,9 @@ } //kDebug() << "rand" << randIndex << rand; - m_pieces[rand] = new Piece(SIZE, i, this); + m_pieces[rand] = new Piece(i, this, m_svg, rand); m_pieces[rand]->hide(); - QObject::connect(m_pieces[rand], SIGNAL(pressed(QGraphicsItem*)), this, SLOT(piecePressed(QGraphicsItem*))); + QObject::connect(m_pieces[rand], SIGNAL(pressed(Piece*)), this, SLOT(piecePressed(Piece*))); if (i == 0) { m_blank = m_pieces[rand]; @@ -93,6 +105,11 @@ b = 0; } qSwap(m_pieces[a], m_pieces[b]); + + // also swap the gamePos of the pieces + int aPos = m_pieces[a]->getGamePos(); + m_pieces[a]->setGamePos(m_pieces[b]->getGamePos()); + m_pieces[b]->setGamePos(aPos); } updatePixmaps(); @@ -155,98 +172,120 @@ void Fifteen::setIdentical() { - KSvgRenderer renderer(QLatin1String(":/images/greensquare.svgz")); - QPixmap pixmap(renderer.defaultSize()); - pixmap.fill(Qt::transparent); - QPainter painter(&pixmap); - renderer.render(&painter); - painter.end(); - - m_pixmap = pixmap; - m_splitPixmap = false; updatePixmaps(); + + // if the pieces are identical then numerals are needed + m_numerals = true; + updateNumerals(); } void Fifteen::updatePixmaps() { - QPixmap pixmap; + int width = contentsRect().size().width() / 4; + int height = contentsRect().size().height() / 4; + // identical images if (!m_splitPixmap) { - pixmap = m_pixmap.scaled(SIZE, SIZE); - m_pixmaps.fill(pixmap); - } - else { - pixmap = m_pixmap.scaled(SIZE * 4, SIZE * 4); - int x = 0; - int y = 0; + m_svg->resize(width, height); - for (int i = 1; i < 16; ++i) { - if ((i - 1) % 4 == 0 && i != 1) { - x = 0; - y = y + SIZE; + for (int i = 0; i < 16; i++) { + m_pieces[i]->setSize(QSizeF(width, height)); + if (m_pieces[i]->getId() != 0) { + m_pieces[i]->setSplitPixmap(m_splitPixmap); } - m_pixmaps[i] = pixmap.copy(x, y, SIZE, SIZE); - x += SIZE; } + return; } + // split pixmap + QPixmap pixmap = m_pixmap.scaled(width * 4, height * 4); + int x = 0; + int y = 0; + for (int i = 1; i < 16; ++i) { + x = ((i - 1) % 4) * width; + y = ((i - 1) / 4) * height; + m_pixmaps[i] = pixmap.copy(x, y, width, height); + } + for (int i = 0; i < 16; ++i) { + m_pieces[i]->setSplitPixmap(m_splitPixmap); + m_pieces[i]->setSize(QSizeF(width, height)); m_pieces[i]->setPixmap(m_pixmaps[m_pieces[i]->getId()]); } } -void Fifteen::piecePressed(QGraphicsItem *item) +void Fifteen::piecePressed(Piece *item) { - if (isAdjacent(item, m_blank)) { - QPointF pos = item->pos(); - Plasma::Animator::self()->moveItem(item, Plasma::Animator::SlideInMovement, m_blank->pos().toPoint()); - m_blank->setPos(pos); + int ix = item->getGameX(); + int iy = item->getGameY(); + int bx = m_blank->getGameX(); + int by = m_blank->getGameY(); + + if (ix == bx && iy != by) { + if (iy > by) { + for (; by < iy; by++) { + // swap the piece at ix,by+1 with blank + swapPieceWithBlank(itemAt(ix, by + 1)); + } + } + else if (iy < by) { + for (; by > iy; by--) { + // swap the piece at ix,by-1 with blank + swapPieceWithBlank(itemAt(ix, by - 1)); + } + } } + else if (iy == by && ix != bx) { + if (ix > bx) { + for (; bx < ix; bx++) { + // swap the piece at bx+1,iy with blank + swapPieceWithBlank(itemAt(bx + 1, iy)); + } + } + else if (ix < bx) { + for (; bx > ix; bx--) { + // swap the piece at bx-1,iy with blank + swapPieceWithBlank(itemAt(bx - 1, iy)); + } + } + } } -bool Fifteen::isAdjacent(QGraphicsItem *a, QGraphicsItem *b) +Piece* Fifteen::itemAt(int gameX, int gameY) { - qreal ax = a->pos().x(); - qreal ay = a->pos().y(); + int gamePos = (gameY * 4) + gameX; + for (int i = 0; i < 16; i++) { + if (m_pieces[i]->getGamePos() == gamePos) { + return m_pieces[i]; + } + } + return NULL; +} - qreal bx = b->pos().x(); - qreal by = b->pos().y(); +void Fifteen::swapPieceWithBlank(Piece *item) +{ + int width = contentsRect().size().width() / 4; + int height = contentsRect().size().height() / 4; - /* - qDebug() << "ax:" << ax << "ay:" << ay; - qDebug() << "bx:" << bx << "by:" << by; - */ + // swap widget positions + QPointF pos = QPointF(item->getGameX() * width, item->getGameY() * height); + Plasma::Animator::self()->moveItem(item, Plasma::Animator::FastSlideInMovement, m_blank->pos().toPoint()); + m_blank->setPos(pos); - // Left - if (ax + SIZE == bx && ay == by) - return true; - // Right - if (ax - SIZE == bx && ay == by) - return true; - // Above - if (ay + SIZE == by && ax == bx) - return true; - // Below - if (ay - SIZE == by && ax == bx) - return true; - - return false; + // swap game positions + int blankPos = m_blank->getGamePos(); + m_blank->setGamePos(item->getGamePos()); + item->setGamePos(blankPos); } void Fifteen::drawPieces() { - int x = 0; - int y = 0; + int width = contentsRect().size().width() / 4; + int height = contentsRect().size().height() / 4; for (int i = 0; i < 16; ++i) { - if (i % 4 == 0 && i != 0) { - x = 0; - y = y + SIZE; - } - - m_pieces.at(i)->setPos(x, y); - m_pieces.at(i)->show(); - x += SIZE; + m_pieces[i]->setPos(m_pieces[i]->getGameX() * width, m_pieces[i]->getGameY() * height); + m_pieces[i]->show(); } } Index: fifteen.h =================================================================== --- fifteen.h (revision 860979) +++ fifteen.h (working copy) @@ -22,6 +22,8 @@ #include <QGraphicsWidget> +#include <Plasma/Svg> + #include "piece.h" class Fifteen : public QGraphicsWidget @@ -29,9 +31,11 @@ Q_OBJECT public: Fifteen(QGraphicsItem *parent = 0); + ~Fifteen(); + void updateGraphics(); public slots: - void piecePressed(QGraphicsItem *item); + void piecePressed(Piece *item); void setSplitPixmap(const QString& path); void setIdentical(); void setNumerals(bool show); @@ -39,7 +43,8 @@ private: void drawPieces(); - bool isAdjacent(QGraphicsItem *a, QGraphicsItem *b); + Piece* itemAt(int gameX, int gameY); + void swapPieceWithBlank(Piece *item); void updatePixmaps(); void clearPieces(); void updateNumerals(); @@ -47,8 +52,9 @@ QVector<Piece *> m_pieces; QVector<QPixmap> m_pixmaps; - QGraphicsItem *m_blank; + Piece *m_blank; bool m_splitPixmap; + Plasma::Svg *m_svg; QPixmap m_pixmap; bool m_numerals; }; Index: piece.cpp =================================================================== --- piece.cpp (revision 860979) +++ piece.cpp (working copy) @@ -29,12 +29,13 @@ #include <KDebug> -Piece::Piece(int size, int id, QGraphicsItem *parent) - : QGraphicsPixmapItem(parent) +Piece::Piece(int id, QGraphicsItem *parent, Plasma::Svg *svg, int gamePos) + : QGraphicsItem(parent) { - m_size = size; m_id = id; m_numeral = true; + m_gamePos = gamePos; + m_svg = svg; } int Piece::getId() @@ -42,6 +43,41 @@ return m_id; } +int Piece::getGameX() +{ + return m_gamePos % 4; +} + +int Piece::getGameY() +{ + return m_gamePos / 4; +} + +int Piece::getGamePos() +{ + return m_gamePos; +} + +void Piece::setGamePos(int gamePos) +{ + m_gamePos = gamePos; +} + +void Piece::setSize(QSizeF size) +{ + m_size = size; +} + +void Piece::setSplitPixmap(bool splitPixmap) +{ + m_splitPixmap = splitPixmap; +} + +void Piece::setPixmap(QPixmap pixmap) +{ + m_pixmap = pixmap; +} + void Piece::showNumeral(bool show) { m_numeral = show; @@ -50,16 +86,28 @@ void Piece::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { + Q_UNUSED(option); + Q_UNUSED(widget); + if (m_id == 0) { return; } - QGraphicsPixmapItem::paint(painter, option, widget); + if (m_splitPixmap) { + painter->drawPixmap(QPoint(0, 0), m_pixmap); + } + else { + // here we assume that the svg has already been resized correctly by Fifteen::updatePixmaps() + m_svg->paint(painter, QPointF(0, 0)); + } if (!m_numeral) { return; } + int width = m_size.width(); + int height = m_size.height(); + QFont font = painter->font(); font.setBold(true); font.setPointSize(14); @@ -72,17 +120,22 @@ pen.setColor(QColor(0, 0, 0, 90)); painter->setPen(pen); - painter->drawText(((m_size / 2) - m.width(text) / 2) + 2, - ((m_size / 2) + m.ascent() / 2) + 2, + painter->drawText(((width / 2) - m.width(text) / 2) + 2, + ((height / 2) + m.ascent() / 2) + 2, text); pen.setColor(QColor(Qt::white)); painter->setPen(pen); - painter->drawText((m_size / 2) - m.width(text) / 2, - (m_size / 2) + m.ascent() / 2, + painter->drawText((width / 2) - m.width(text) / 2, + (height / 2) + m.ascent() / 2, text); } +QRectF Piece::boundingRect() const +{ + return QRectF(QPointF(0, 0), m_size); +} + void Piece::mousePressEvent(QGraphicsSceneMouseEvent *event) { Q_UNUSED(event); Index: fifteenPuzzle.cpp =================================================================== --- fifteenPuzzle.cpp (revision 860979) +++ fifteenPuzzle.cpp (working copy) @@ -59,14 +59,14 @@ } updateBoard(); + board->updateGraphics(); } void FifteenPuzzle::constraintsEvent(Plasma::Constraints constraints) { if (constraints & Plasma::SizeConstraint) { - QSizeF size = contentsRect().size(); - board->resetTransform(); - board->scale(size.width() / 192, size.height() / 192); + board->resize(contentsRect().size()); + board->updateGraphics(); } } Index: piece.h =================================================================== --- piece.h (revision 860979) +++ piece.h (working copy) @@ -23,27 +23,40 @@ #include <QGraphicsItem> #include <QObject> +#include <Plasma/Svg> -class Piece : public QObject, public QGraphicsPixmapItem +class Piece : public QObject, public QGraphicsItem { Q_OBJECT public: - Piece(int size, int id, QGraphicsItem * parent); + Piece(int id, QGraphicsItem * parent, Plasma::Svg *svg, int gamePos); int getId(); void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); + QRectF boundingRect() const; void showNumeral(bool show); + int getGameX(); + int getGameY(); + int getGamePos(); + void setGamePos(int gamePos); + void setSize(QSizeF size); + void setSplitPixmap(bool splitPixmap); + void setPixmap(QPixmap pixmap); private: int m_id; - int m_size; bool m_numeral; + int m_gamePos; + bool m_splitPixmap; + QSizeF m_size; + Plasma::Svg *m_svg; + QPixmap m_pixmap; protected: void mousePressEvent(QGraphicsSceneMouseEvent *event); signals: - void pressed(QGraphicsItem *item); + void pressed(Piece *item); }; #endif
_______________________________________________ Plasma-devel mailing list Plasma-devel@kde.org https://mail.kde.org/mailman/listinfo/plasma-devel