The menu option "Vibration effects" now works
[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)
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,100);
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
181 void SeaScene::spreadGhosts(int ghosts)
182 {
183
184
185     //the octopuses and the ship may have moved from their original positions,
186     //so the list of free slots must be adjusted to exclude their current positions
187
188     QList<QPointF> temporarilyReservedSlots;
189
190     foreach (QGraphicsItem* pItem, movingItems_)
191     {
192         if (pItem == NULL)
193         {
194  //           qDebug() << "NULL item in movingItems_";
195             continue;
196         }
197
198         //round x and y down to fit the slot size
199         int x = pItem->x();
200         x = x/40;
201         x = x*40;
202
203         int y = pItem->y();
204         y = y/40;
205         y=y*40;
206
207
208         QPointF position (x,y);
209
210         //remove the tiles (potentially) occupied by the item from free slots and place in temp list if was in the list before
211
212         if (freeTiles_.removeOne(position))
213             temporarilyReservedSlots.append(position);
214
215
216         position.setX(x+40);
217
218         if (freeTiles_.removeOne(position))
219             temporarilyReservedSlots.append(position);
220
221         position.setY(y+40);
222
223         if (freeTiles_.removeOne(position))
224             temporarilyReservedSlots.append(position);
225
226         position.setX(x);
227
228         if (freeTiles_.removeOne(position))
229             temporarilyReservedSlots.append(position);
230
231     }
232
233
234     //spread ghosts in random free slots
235
236     for (int i=0; i < ghosts; i++)
237     {
238         QPointF * pPosition = findRandomFreeSlot();
239
240         //If there was no room no point to continue
241         if (pPosition == NULL)
242             return;
243
244         QPixmap ghostPixmap(":/pix/aave.png");
245         QGraphicsPixmapItem * pGhost = addPixmap(ghostPixmap);
246         pGhost->setData(0,"ghost");
247         pGhost->setPos(*pPosition);
248         delete pPosition;
249     }
250
251     //return the slots occupied by moving items to free slots
252     freeTiles_.append(temporarilyReservedSlots);
253
254     //clear temp for the next round
255     temporarilyReservedSlots.clear();
256 }
257
258 QPointF* SeaScene::findRandomFreeSlot()
259 {
260     if (freeTiles_.isEmpty())
261         return NULL;
262
263     int index = qrand()%freeTiles_.size();
264
265 //    qDebug()  << index << " index";
266     return new QPointF (freeTiles_.takeAt(index));
267
268 }
269
270 void SeaScene::removeGhost(QGraphicsItem *pGhost)
271 {
272     removeItem(pGhost);  //remove the item from scene
273     freeTiles_.append(pGhost->scenePos()); //add the item's position to free slots
274     delete pGhost;
275     ghostsLeft_--;
276     if (ghostsLeft_ == 0)
277     {
278         emit allGhostsPicked();
279  //       qDebug() << "All ghosts picked!";
280     }
281 }
282
283 void SeaScene::ghostsDropped(int ghosts)
284 {
285     ghostsLeft_ += ghosts;
286
287     spreadGhosts(ghosts);
288 }
289
290 void SeaScene::pause(bool paused)
291 {
292     //    qDebug() << "pause pressed " << paused;
293         if (paused_ == paused)
294                 return;
295
296         paused_ = paused;
297
298         if (paused == false)
299         {
300      //       qDebug() << "starting to move again";
301             emit pauseOff();
302             screenLitKeeper_.keepScreenLit(true);
303         }
304
305         else
306         {
307      //       qDebug("about to stop movement");
308             emit pauseOn();
309             screenLitKeeper_.keepScreenLit(false);
310         }
311 }
312
313 void SeaScene::vibrationActivate(bool on)
314 {
315     emit vibrationActivated(on);
316 }