2 Image Puzzle - A set your pieces straight game
3 Copyright (C) 2009 Timo Härkönen
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "puzzleitem.h"
22 #include "introitem.h"
24 #include <QGraphicsScene>
27 #include <QPropertyAnimation>
28 #include <QParallelAnimationGroup>
30 #include <QMessageBox>
34 GameView *GameView::instance_ = 0;
36 GameView::GameView(QWidget *parent) :
39 scene_ = new QGraphicsScene;
43 introItem_ = new IntroItem;
44 introItem_->setText("Select new game from menu to play");
45 scene_->addItem(introItem_);
50 qsrand(QDateTime::currentDateTime().toTime_t());
53 GameView *GameView::instance()
56 instance_ = new GameView;
62 QList<PuzzleItem *> GameView::pieces() const
67 void GameView::setPieces(const QList<PuzzleItem *> pieces)
69 if(pieces.isEmpty()) {
70 qDebug() << "Empty list @ GameView::setPieces";
74 QList<QGraphicsItem *> previousItems = scene_->items();
75 if(!previousItems.isEmpty()) {
76 foreach(QGraphicsItem *item, previousItems) {
77 scene_->removeItem(item);
83 int horizontalCount = 0;
85 // Find out board size
86 if(pieces_.count() == 12) {
89 else if(pieces_.count() == 20) {
93 qDebug() << "Invalid piece count @ GameView::setPieces";
94 qDebug() << QString("Count was %1").arg(pieces_.count());
98 int verticalCount = pieces_.count() / horizontalCount;
99 horizontalStep_ = IMAGE_WIDTH / horizontalCount + 5;
100 verticalStep_ = IMAGE_HEIGHT / verticalCount + 5;
104 // Set pieces to their correct positions
105 for(int i = 0; i < verticalCount; ++i) {
106 for(int j = 0; j < horizontalCount; ++j) {
107 scene_->addItem(pieces_.at(pieceNumber));
108 QPointF point(j * horizontalStep_, i * verticalStep_);
109 pieces_.at(pieceNumber)->setPos(point);
110 pieces_.at(pieceNumber)->setCorrectPlace(point);
111 pieces_.at(pieceNumber)->setCurrentPlace(point);
117 QTimer::singleShot(750, this, SLOT(shufflePieces()));
120 void GameView::shufflePieces()
122 if(pieces_.isEmpty()) {
123 qDebug() << "Empty list @ GameView::shufflePieces";
127 // Give pieces ramdom locations
128 int rounds = 5; //TODO
129 for(int j = 0; j < rounds; ++j) {
130 for(int i = 0; i < pieces_.count(); ++i) {
133 while(changeIndex == i) {
134 changeIndex = qrand() % pieces_.count();
136 tmp = pieces_.at(changeIndex)->currentPlace();
137 pieces_.at(changeIndex)->setCurrentPlace(pieces_.at(i)->currentPlace());
138 pieces_.at(i)->setCurrentPlace(tmp);
142 // TODO Animate transitions to new locations
143 QParallelAnimationGroup *animationGroup = new QParallelAnimationGroup(this);
144 for(int i = 0; i < pieces_.count(); ++i) {
145 QPropertyAnimation *animation = new QPropertyAnimation(pieces_.at(i), "pos");
146 animation->setStartValue(pieces_.at(i)->correctPlace());
147 animation->setEndValue(pieces_.at(i)->currentPlace());
148 animation->setDuration(750);
149 animation->setEasingCurve(QEasingCurve::InOutCirc);
150 animationGroup->addAnimation(animation);
152 animationGroup->start();
155 int hiddenPiece = qrand() % pieces_.count();
156 emptyPlace_ = pieces_.at(hiddenPiece)->currentPlace();
157 pieces_.at(hiddenPiece)->hide();
158 hiddenIndex_ = hiddenPiece;
163 QPointF GameView::emptyPlace()
168 void GameView::setEmptyPlace(const QPointF &place)
173 bool GameView::areAllPiecesOk() const
175 for(int i = 0; i < pieces_.count(); ++i) {
177 if(i == hiddenIndex_) {
180 // Id piece is not in it's place
181 else if(pieces_.at(i)->correctPlace() != pieces_.at(i)->currentPlace()) {
185 // Show hidden piece and move it to it's place
186 pieces_.at(hiddenIndex_)->show();
187 pieces_.at(hiddenIndex_)->moveMeTo(emptyPlace_);
189 // Set all pieces not movable
190 for(int i = 0; i < pieces_.count(); ++i) {
191 pieces_.at(i)->setMovable(false);
194 // Show dialog with move count
195 QMessageBox::about(const_cast<GameView *>(this), tr("You won"), QString("Puzzle completed with %1 moves").arg(PuzzleItem::moveCount()));
200 void GameView::setMovingPieces()
202 if(pieces_.isEmpty()) {
203 qDebug() << "Empty list @ GameView::setMovingPieces";
207 QPointF point = QPointF();
208 for(int i = 0; i < pieces_.count(); ++i) {
209 point = pieces_.at(i)->currentPlace();
211 // Is piece on the left side of the empty space
212 if(emptyPlace_.y() == point.y() && point.x() + horizontalStep_ == emptyPlace_.x()) {
213 pieces_.at(i)->setMovable(true);
216 // Is piece on the right side of the empty space
217 else if(emptyPlace_.y() == point.y() && point.x() - horizontalStep_ == emptyPlace_.x()) {
218 pieces_.at(i)->setMovable(true);
221 // Is piece below the empty space
222 else if(emptyPlace_.x() == point.x() && point.y() - verticalStep_ == emptyPlace_.y()) {
223 pieces_.at(i)->setMovable(true);
226 // Is piece on top of the empty space
227 else if(emptyPlace_.x() == point.x() && point.y() + verticalStep_ == emptyPlace_.y()) {
228 pieces_.at(i)->setMovable(true);
231 // The piece is somewhere else
233 pieces_.at(i)->setMovable(false);