Merge branch 'randomize'
[ghostsoverboard] / seascene.cpp
1 #include "seascene.h"
2 #include "timercontrolledtursas.h"
3 #include "ship.h"
4 #include <QGraphicsPixmapItem>
5 #include <QDebug>
6 #include <QMessageBox>
7 #include <QTime>
8
9 const QString ghostImageFilename_ = ":/pix/aave.png";
10 const QString rockImageFilename_ =":/pix/kari.png";
11 const QString octopusImageFilename_= ":/pix/tursas.png";
12
13
14 SeaScene::SeaScene(QObject *parent) :
15     QGraphicsScene(parent)
16 {
17     //set background
18
19     QPixmap waves (":/pix/meri.png");
20     waves.scaled(20,20);
21     setBackgroundBrush(QBrush(waves));
22
23     //set random seed
24
25     qsrand(QTime::currentTime().msec()+2);  //+2 to avoid setting it to 1
26
27 }
28
29 void SeaScene::setupMap(int ghosts, int rocks, int octopuses)
30 {
31     //empty the map
32
33     clear();
34
35     //empty the list of moving items
36
37     movingItems_.clear();
38
39     //empty the list of free slots
40     freeTiles_.clear();
41
42     //fill the list of free slots
43
44     int numberOfXTiles  = width() / 40;
45     int numberOfYTiles = height() /40;
46
47     qDebug() << numberOfXTiles << " slots in x direction";
48     qDebug() << numberOfYTiles << " slots in y rirection";
49
50     for (int i = 0; i < numberOfXTiles; i++ )
51     {
52         for (int j = 0; j < numberOfYTiles; j++)
53         {
54             freeTiles_.append(QPointF(i*40,j*40));
55         }
56     }
57
58
59     //spread the rocks
60
61     for (int i = 0; i < rocks; i++)
62     {
63         QPointF * pPosition = findRandomFreeSlot();
64
65         qDebug() << "Found a place for a rock";
66
67         //If there was no room no point to continue
68         if (pPosition == NULL)
69             break;
70
71         QPixmap rockPixmap (":/pix/kari.png");
72         QGraphicsPixmapItem * pRock = addPixmap(rockPixmap);
73         pRock->setData(0,"rock");
74         pRock->setPos(*pPosition);
75         delete pPosition;
76
77     }
78
79     //spread the ghosts
80
81     ghostsLeft_ = ghosts;
82     spreadGhosts(ghosts);
83
84
85
86     //spread the octopuses
87
88
89     for (int i=0; i < octopuses; i++)
90     {
91         QPointF * pPosition = findRandomFreeSlot();
92
93         //If there was no room no point to continue
94         if (pPosition == NULL)
95             break;
96
97     QPixmap octopusPixmap (":/pix/tursas.png");
98     TimerControlledTursas * pOctopus = new TimerControlledTursas (octopusPixmap,100);
99     pOctopus->setData(0,"octopus");
100     pOctopus->setPos(*pPosition);
101     addItem(pOctopus);
102     pOctopus->startMoving();
103     movingItems_.append(pOctopus);
104     delete pPosition;
105
106     }
107
108
109     //place the ship
110
111     QPointF * pPosition = findRandomFreeSlot();
112     if (pPosition == NULL)
113     {
114         // Game cannot begin without a free position for ship, so give an error message and return
115
116         QMessageBox::critical(NULL,"Error! Too many objects on screen","No free space to place the ship. The game cannot start. Please choose another level.");
117         return;
118     }
119
120     QList<QPixmap> shipImages;
121     shipImages.append(QPixmap(":/pix/laiva.png"));
122     shipImages.append(QPixmap(":/pix/laiva_1aave.png"));
123     shipImages.append(QPixmap(":/pix/laiva_2aave.png"));
124     shipImages.append(QPixmap(":/pix/laiva_3aave.png"));
125     shipImages.append(QPixmap(":/pix/laiva_4aave.png"));
126     shipImages.append(QPixmap(":/pix/laiva_5aave.png"));
127     shipImages.append(QPixmap(":/pix/laiva_6aave.png"));
128     shipImages.append(QPixmap(":/pix/laiva_7aave.png"));
129     shipImages.append(QPixmap(":/pix/laiva_8aave.png"));
130     shipImages.append(QPixmap(":/pix/laiva_9aave.png"));
131     shipImages.append(QPixmap(":/pix/laiva_10aave.png"));
132
133     Ship * pShip = new Ship (shipImages);
134     pShip->setData(0,"ship");
135     pShip->setPos(*pPosition);
136     addItem(pShip);
137     connect(pShip,SIGNAL(pickingGhost(QGraphicsItem*)),this, SLOT(removeGhost(QGraphicsItem*)) );
138     connect(pShip,SIGNAL(droppingGhosts(int)),this,SLOT(ghostsDropped(int)));
139     pShip->startMoving();
140     movingItems_.append(pShip);
141     delete pPosition;
142 }
143
144
145 void SeaScene::spreadGhosts(int ghosts)
146 {
147
148
149     //the octopuses and the ship may have moved from their original positions,
150     //so the list of free slots must be adjusted to exclude their current positions
151
152     QList<QPointF> temporarilyReservedSlots;
153
154     foreach (QGraphicsItem* pItem, movingItems_)
155     {
156         if (pItem == NULL)
157         {
158  //           qDebug() << "NULL item in movingItems_";
159             continue;
160         }
161
162         //round x and y down to fit the slot size
163         int x = pItem->x();
164         x = x/40;
165         x = x*40;
166
167         int y = pItem->y();
168         y = y/40;
169         y=y*40;
170
171
172         QPointF position (x,y);
173
174         //remove the tiles (potentially) occupied by the item from free slots and place in temp list if was in the list before
175
176         if (freeTiles_.removeOne(position))
177             temporarilyReservedSlots.append(position);
178
179
180         position.setX(x+40);
181
182         if (freeTiles_.removeOne(position))
183             temporarilyReservedSlots.append(position);
184
185         position.setY(y+40);
186
187         if (freeTiles_.removeOne(position))
188             temporarilyReservedSlots.append(position);
189
190         position.setX(x);
191
192         if (freeTiles_.removeOne(position))
193             temporarilyReservedSlots.append(position);
194
195     }
196
197
198     //spread ghosts in random free slots
199
200     for (int i=0; i < ghosts; i++)
201     {
202         QPointF * pPosition = findRandomFreeSlot();
203
204         //If there was no room no point to continue
205         if (pPosition == NULL)
206             return;
207
208         QPixmap ghostPixmap(":/pix/aave.png");
209         QGraphicsPixmapItem * pGhost = addPixmap(ghostPixmap);
210         pGhost->setData(0,"ghost");
211         pGhost->setPos(*pPosition);
212         delete pPosition;
213     }
214
215     //return the slots occupied by moving items to free slots
216     freeTiles_.append(temporarilyReservedSlots);
217
218     //clear temp for the next round
219     temporarilyReservedSlots.clear();
220 }
221
222 QPointF* SeaScene::findRandomFreeSlot()
223 {
224     if (freeTiles_.isEmpty())
225         return NULL;
226
227     int index = qrand()%freeTiles_.size();
228
229     qDebug()  << index << " index";
230     return new QPointF (freeTiles_.takeAt(index));
231
232 }
233
234 void SeaScene::removeGhost(QGraphicsItem *pGhost)
235 {
236     removeItem(pGhost);  //remove the item from scene
237     freeTiles_.append(pGhost->scenePos()); //add the item's position to free slots
238     delete pGhost;
239     ghostsLeft_--;
240     if (ghostsLeft_ == 0)
241     {
242         //here whatever happens when a level is complete / a signal
243         qDebug() << "All ghosts picked!";
244     }
245 }
246
247 void SeaScene::ghostsDropped(int ghosts)
248 {
249     ghostsLeft_ += ghosts;
250
251     spreadGhosts(ghosts);
252 }