339624abea1c85c92851963beb2f4efb777dc2eb
[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     Ship * pShip = new Ship (QPixmap(":/pix/laiva.png"));
121     pShip->setData(0,"ship");
122     pShip->setPos(*pPosition);
123     addItem(pShip);
124     connect(pShip,SIGNAL(pickingGhost(QGraphicsItem*)),this, SLOT(removeGhost(QGraphicsItem*)) );
125     connect(pShip,SIGNAL(droppingGhosts(int)),this,SLOT(ghostsDropped(int)));
126     pShip->startMoving();
127     movingItems_.append(pShip);
128     delete pPosition;
129 }
130
131
132 void SeaScene::spreadGhosts(int ghosts)
133 {
134
135
136     //the octopuses and the ship may have moved from their original positions,
137     //so the list of free slots must be adjusted to exclude their current positions
138
139     QList<QPointF> temporarilyReservedSlots;
140
141     foreach (QGraphicsItem* pItem, movingItems_)
142     {
143         if (pItem == NULL)
144         {
145  //           qDebug() << "NULL item in movingItems_";
146             continue;
147         }
148
149         //round x and y down to fit the slot size
150         int x = pItem->x();
151         x = x/40;
152         x = x*40;
153
154         int y = pItem->y();
155         y = y/40;
156         y=y*40;
157
158
159         QPointF position (x,y);
160
161         //remove the tiles (potentially) occupied by the item from free slots and place in temp list if was in the list before
162
163         if (freeTiles_.removeOne(position))
164             temporarilyReservedSlots.append(position);
165
166
167         position.setX(x+40);
168
169         if (freeTiles_.removeOne(position))
170             temporarilyReservedSlots.append(position);
171
172         position.setY(y+40);
173
174         if (freeTiles_.removeOne(position))
175             temporarilyReservedSlots.append(position);
176
177         position.setX(x);
178
179         if (freeTiles_.removeOne(position))
180             temporarilyReservedSlots.append(position);
181
182     }
183
184
185     //spread ghosts in random free slots
186
187     for (int i=0; i < ghosts; i++)
188     {
189         QPointF * pPosition = findRandomFreeSlot();
190
191         //If there was no room no point to continue
192         if (pPosition == NULL)
193             return;
194
195         QPixmap ghostPixmap(":/pix/aave.png");
196         QGraphicsPixmapItem * pGhost = addPixmap(ghostPixmap);
197         pGhost->setData(0,"ghost");
198         pGhost->setPos(*pPosition);
199         delete pPosition;
200     }
201
202     //return the slots occupied by moving items to free slots
203     freeTiles_.append(temporarilyReservedSlots);
204
205     //clear temp for the next round
206     temporarilyReservedSlots.clear();
207 }
208
209 QPointF* SeaScene::findRandomFreeSlot()
210 {
211     if (freeTiles_.isEmpty())
212         return NULL;
213
214     int index = qrand()%freeTiles_.size();
215
216     qDebug()  << index << " index";
217     return new QPointF (freeTiles_.takeAt(index));
218
219 }
220
221 void SeaScene::removeGhost(QGraphicsItem *pGhost)
222 {
223     removeItem(pGhost);  //remove the item from scene
224     freeTiles_.append(pGhost->scenePos()); //add the item's position to free slots
225     delete pGhost;
226     ghostsLeft_--;
227     if (ghostsLeft_ == 0)
228     {
229         //here whatever happens when a level is complete / a signal
230         qDebug() << "All ghosts picked!";
231     }
232 }
233
234 void SeaScene::ghostsDropped(int ghosts)
235 {
236     ghostsLeft_ += ghosts;
237
238     spreadGhosts(ghosts);
239 }