Added copyright & licence info where missing
[ghostsoverboard] / seascene.cpp
1 /**************************************************************************
2         Ghosts Overboard - a game for Maemo 5
3
4         Copyright (C) 2011  Heli Hyvättinen
5
6         This file is part of Ghosts Overboard
7
8         Ghosts Overboard is free software: you can redistribute it and/or modify
9         it under the terms of the GNU General Public License as published by
10         the Free Software Foundation, either version 2 of the License, or
11         (at your option) any later version.
12
13         This program is distributed in the hope that it will be useful,
14         but WITHOUT ANY WARRANTY; without even the implied warranty of
15         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16         GNU General Public License for more details.
17
18         You should have received a copy of the GNU General Public License
19         along with this program.  If not, see <http://www.gnu.org/licenses/>.
20
21 **************************************************************************/
22
23 #include "seascene.h"
24 #include "octopus.h"
25 #include "ship.h"
26 #include <QGraphicsPixmapItem>
27 #include <QDebug>
28 #include <QMessageBox>
29 #include <QTime>
30
31 const QString ghostImageFilename_ = ":/pix/aave.png";
32 const QString rockImageFilename_ =":/pix/kari.png";
33 const QString octopusImageFilename_= ":/pix/tursas.png";
34
35
36 SeaScene::SeaScene(QObject *parent) :
37     QGraphicsScene(parent)
38 {
39     paused_ = false;
40     screenLitKeeper_.keepScreenLit(true);
41
42     //set background
43
44     QPixmap waves (":/pix/meri.png");
45     waves.scaled(20,20);
46     setBackgroundBrush(QBrush(waves));
47
48     //set random seed
49
50     qsrand(QTime::currentTime().msec()+2);  //+2 to avoid setting it to 1
51
52
53
54 }
55
56 void SeaScene::setupMap(int ghosts, int rocks, int octopuses, int octopusSpeed)
57 {
58     //empty the map
59
60     clear();
61
62     //empty the list of moving items
63
64     movingItems_.clear();
65
66     //empty the list of free slots
67     freeTiles_.clear();
68
69     //fill the list of free slots
70
71     int numberOfXTiles  = width() / 40;
72     int numberOfYTiles = height() /40;
73
74 //    qDebug() << numberOfXTiles << " slots in x direction";
75 //    qDebug() << numberOfYTiles << " slots in y rirection";
76
77     for (int i = 0; i < numberOfXTiles; i++ )
78     {
79         for (int j = 0; j < numberOfYTiles; j++)
80         {
81             freeTiles_.append(QPointF(i*40,j*40));
82         }
83     }
84
85
86     //spread the rocks
87
88     for (int i = 0; i < rocks; i++)
89     {
90         QPointF * pPosition = findRandomFreeSlot();
91
92         //If there was no room no point to continue
93         if (pPosition == NULL)
94             break;
95
96         QPixmap rockPixmap (":/pix/kari.png");
97         QGraphicsPixmapItem * pRock = addPixmap(rockPixmap);
98         pRock->setData(0,"rock");
99         pRock->setPos(*pPosition);
100         delete pPosition;
101
102     }
103
104     //spread the ghosts
105
106     ghostsLeft_ = ghosts;
107     spreadGhosts(ghosts);
108
109
110
111     //spread the octopuses
112
113     QList <Octopus*> octopusList;
114
115     for (int i=0; i < octopuses; i++)
116     {
117         QPointF * pPosition = findRandomFreeSlot();
118
119         //If there was no room no point to continue
120         if (pPosition == NULL)
121             break;
122
123     QPixmap octopusPixmap (":/pix/tursas.png");
124     Octopus * pOctopus = new Octopus(octopusPixmap,octopusSpeed);
125     pOctopus->setData(0,"octopus");
126     pOctopus->setPos(*pPosition);
127     addItem(pOctopus);
128     pOctopus->startMoving();
129     movingItems_.append(pOctopus);
130     connect(this,SIGNAL(pauseOn()),pOctopus,SLOT(stopMoving()));
131     connect(this,SIGNAL(pauseOff()),pOctopus,SLOT(startMoving()));
132     octopusList.append(pOctopus);
133     delete pPosition;
134
135     }
136
137
138     //place the ship
139
140     QPointF * pPosition = findRandomFreeSlot();
141     if (pPosition == NULL)
142     {
143         // Game cannot begin without a free position for ship, so give an error message and return
144
145         QMessageBox::critical(NULL,"Error! Too many objects on screen","No free space to place the ship. The game cannot start. Please choose another level.");
146         return;
147     }
148
149     QList<QPixmap> shipImages;
150     shipImages.append(QPixmap(":/pix/laiva.png"));
151     shipImages.append(QPixmap(":/pix/laiva_1aave.png"));
152     shipImages.append(QPixmap(":/pix/laiva_2aave.png"));
153     shipImages.append(QPixmap(":/pix/laiva_3aave.png"));
154     shipImages.append(QPixmap(":/pix/laiva_4aave.png"));
155     shipImages.append(QPixmap(":/pix/laiva_5aave.png"));
156     shipImages.append(QPixmap(":/pix/laiva_6aave.png"));
157     shipImages.append(QPixmap(":/pix/laiva_7aave.png"));
158     shipImages.append(QPixmap(":/pix/laiva_8aave.png"));
159     shipImages.append(QPixmap(":/pix/laiva_9aave.png"));
160     shipImages.append(QPixmap(":/pix/laiva_10aave.png"));
161
162     Ship * pShip = new Ship (shipImages);
163     pShip->setData(0,"ship");
164     pShip->setPos(*pPosition);
165     addItem(pShip);
166     connect(pShip,SIGNAL(pickingGhost(QGraphicsItem*)),this, SLOT(removeGhost(QGraphicsItem*)) );
167     connect(pShip,SIGNAL(droppingGhosts(int)),this,SLOT(ghostsDropped(int)));
168     connect(this,SIGNAL(vibrationActivated(bool)),pShip,SLOT(setVibrationActivate(bool)));
169     pShip->startMoving();
170     movingItems_.append(pShip);
171     connect(this,SIGNAL(pauseOn()),pShip,SLOT(stopMoving()));
172     connect(this,SIGNAL(pauseOff()),pShip,SLOT(startMoving()));
173     foreach (Octopus* pOctopus, octopusList)
174     {
175         connect(pOctopus,SIGNAL(droppingGhosts()),pShip,SLOT(dropAllGhosts()));
176     }
177     delete pPosition;
178 }
179
180 void SeaScene::setupMap(Level level)
181 {
182     setupMap(level.getNumberOfGhosts(),level.getNumberOfRocks(),level.getNumberOfOctopuses(),level.getOctopusSpeed());
183 }
184
185 void SeaScene::spreadGhosts(int ghosts)
186 {
187
188
189     //the octopuses and the ship may have moved from their original positions,
190     //so the list of free slots must be adjusted to exclude their current positions
191
192     QList<QPointF> temporarilyReservedSlots;
193
194     foreach (QGraphicsItem* pItem, movingItems_)
195     {
196         if (pItem == NULL)
197         {
198  //           qDebug() << "NULL item in movingItems_";
199             continue;
200         }
201
202         //round x and y down to fit the slot size
203         int x = pItem->x();
204         x = x/40;
205         x = x*40;
206
207         int y = pItem->y();
208         y = y/40;
209         y=y*40;
210
211
212         QPointF position (x,y);
213
214         //remove the tiles (potentially) occupied by the item from free slots and place in temp list if was in the list before
215
216         if (freeTiles_.removeOne(position))
217             temporarilyReservedSlots.append(position);
218
219
220         position.setX(x+40);
221
222         if (freeTiles_.removeOne(position))
223             temporarilyReservedSlots.append(position);
224
225         position.setY(y+40);
226
227         if (freeTiles_.removeOne(position))
228             temporarilyReservedSlots.append(position);
229
230         position.setX(x);
231
232         if (freeTiles_.removeOne(position))
233             temporarilyReservedSlots.append(position);
234
235     }
236
237
238     //spread ghosts in random free slots
239
240     for (int i=0; i < ghosts; i++)
241     {
242         QPointF * pPosition = findRandomFreeSlot();
243
244         //If there was no room no point to continue
245         if (pPosition == NULL)
246             return;
247
248         QPixmap ghostPixmap(":/pix/aave.png");
249         QGraphicsPixmapItem * pGhost = addPixmap(ghostPixmap);
250         pGhost->setData(0,"ghost");
251         pGhost->setPos(*pPosition);
252         delete pPosition;
253     }
254
255     //return the slots occupied by moving items to free slots
256     freeTiles_.append(temporarilyReservedSlots);
257
258     //clear temp for the next round
259     temporarilyReservedSlots.clear();
260 }
261
262 QPointF* SeaScene::findRandomFreeSlot()
263 {
264     if (freeTiles_.isEmpty())
265         return NULL;
266
267     int index = qrand()%freeTiles_.size();
268
269 //    qDebug()  << index << " index";
270     return new QPointF (freeTiles_.takeAt(index));
271
272 }
273
274 void SeaScene::removeGhost(QGraphicsItem *pGhost)
275 {
276     removeItem(pGhost);  //remove the item from scene
277     freeTiles_.append(pGhost->scenePos()); //add the item's position to free slots
278     delete pGhost;
279     ghostsLeft_--;
280     if (ghostsLeft_ == 0)
281     {
282         emit allGhostsPicked();
283  //       qDebug() << "All ghosts picked!";
284     }
285 }
286
287 void SeaScene::ghostsDropped(int ghosts)
288 {
289     ghostsLeft_ += ghosts;
290
291     spreadGhosts(ghosts);
292 }
293
294 void SeaScene::pause(bool paused)
295 {
296     //    qDebug() << "pause pressed " << paused;
297         if (paused_ == paused)
298                 return;
299
300         paused_ = paused;
301
302         if (paused == false)
303         {
304      //       qDebug() << "starting to move again";
305             emit pauseOff();
306             screenLitKeeper_.keepScreenLit(true);
307         }
308
309         else
310         {
311      //       qDebug("about to stop movement");
312             emit pauseOn();
313             screenLitKeeper_.keepScreenLit(false);
314         }
315 }
316
317 void SeaScene::vibrationActivate(bool on)
318 {
319     emit vibrationActivated(on);
320 }