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
[email protected]
https://mail.kde.org/mailman/listinfo/plasma-devel