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() == EASY_PIECE_COUNT) {
87 horizontalCount = EASY_HORIZONTAL_COUNT;
89 else if(pieces_.count() == HARD_PIECE_COUNT) {
90 horizontalCount = HARD_HORIZONTAL_COUNT;
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);
112 pieces_.at(pieceNumber)->setDrawNumber(true);
118 QTimer::singleShot(750, this, SLOT(shufflePieces()));
121 void GameView::shufflePieces()
123 if(pieces_.isEmpty()) {
124 qDebug() << "Empty list @ GameView::shufflePieces";
128 // Give pieces ramdom locations
129 int rounds = 5; //TODO
130 for(int j = 0; j < rounds; ++j) {
131 for(int i = 0; i < pieces_.count(); ++i) {
134 while(changeIndex == i) {
135 changeIndex = qrand() % pieces_.count();
137 tmp = pieces_.at(changeIndex)->currentPlace();
138 pieces_.at(changeIndex)->setCurrentPlace(pieces_.at(i)->currentPlace());
139 pieces_.at(i)->setCurrentPlace(tmp);
143 // TODO Animate transitions to new locations
144 QParallelAnimationGroup *animationGroup = new QParallelAnimationGroup(this);
145 for(int i = 0; i < pieces_.count(); ++i) {
146 QPropertyAnimation *animation = new QPropertyAnimation(pieces_.at(i), "pos");
147 animation->setStartValue(pieces_.at(i)->correctPlace());
148 animation->setEndValue(pieces_.at(i)->currentPlace());
149 animation->setDuration(750);
150 animation->setEasingCurve(QEasingCurve::InOutCirc);
151 animationGroup->addAnimation(animation);
153 animationGroup->start();
156 int hiddenPiece = qrand() % pieces_.count();
157 emptyPlace_ = pieces_.at(hiddenPiece)->currentPlace();
158 pieces_.at(hiddenPiece)->hide();
159 hiddenIndex_ = hiddenPiece;
164 QPointF GameView::emptyPlace()
169 void GameView::setEmptyPlace(const QPointF &place)
174 bool GameView::areAllPiecesOk() const
176 for(int i = 0; i < pieces_.count(); ++i) {
178 if(i == hiddenIndex_) {
181 // Id piece is not in it's place
182 else if(pieces_.at(i)->correctPlace() != pieces_.at(i)->currentPlace()) {
186 // Show hidden piece and move it to it's place
187 pieces_.at(hiddenIndex_)->show();
188 pieces_.at(hiddenIndex_)->moveMeTo(emptyPlace_);
190 // Set all pieces not movable and hide numbers
191 for(int i = 0; i < pieces_.count(); ++i) {
192 pieces_.at(i)->setMovable(false);
193 pieces_.at(i)->setDrawNumber(false);
196 // Show dialog with move count
197 QMessageBox::about(const_cast<GameView *>(this), tr("You won"), QString("Puzzle completed with %1 moves").arg(PuzzleItem::moveCount()));
202 void GameView::setMovingPieces()
204 if(pieces_.isEmpty()) {
205 qDebug() << "Empty list @ GameView::setMovingPieces";
209 QPointF point = QPointF();
210 for(int i = 0; i < pieces_.count(); ++i) {
211 point = pieces_.at(i)->currentPlace();
213 // Is piece on the left side of the empty space
214 if(emptyPlace_.y() == point.y() && point.x() + horizontalStep_ == emptyPlace_.x()) {
215 pieces_.at(i)->setMovable(true);
218 // Is piece on the right side of the empty space
219 else if(emptyPlace_.y() == point.y() && point.x() - horizontalStep_ == emptyPlace_.x()) {
220 pieces_.at(i)->setMovable(true);
223 // Is piece below the empty space
224 else if(emptyPlace_.x() == point.x() && point.y() - verticalStep_ == emptyPlace_.y()) {
225 pieces_.at(i)->setMovable(true);
228 // Is piece on top of the empty space
229 else if(emptyPlace_.x() == point.x() && point.y() + verticalStep_ == emptyPlace_.y()) {
230 pieces_.at(i)->setMovable(true);
233 // The piece is somewhere else
235 pieces_.at(i)->setMovable(false);