summaryrefslogtreecommitdiffstats
path: root/pacman-c++/common/sceneholder.cpp
diff options
context:
space:
mode:
authormanuel <manuel@mausz.at>2011-05-05 00:57:07 +0200
committermanuel <manuel@mausz.at>2011-05-05 00:57:07 +0200
commitce48af53646cd9e7ec762fc1ac176b3aa620b11d (patch)
treef8fbf2cae8c7d0cbac2696a8f4cf94410bfb4928 /pacman-c++/common/sceneholder.cpp
parente54ccad07e256ba877bd41d70bd358bd0085bd1e (diff)
downloadfoop-ce48af53646cd9e7ec762fc1ac176b3aa620b11d.tar.gz
foop-ce48af53646cd9e7ec762fc1ac176b3aa620b11d.tar.bz2
foop-ce48af53646cd9e7ec762fc1ac176b3aa620b11d.zip
- refactorized the whole project and made a few subprojects
- replaced tcp with enet - added connect dialog - some smaller bugfixes
Diffstat (limited to 'pacman-c++/common/sceneholder.cpp')
-rw-r--r--pacman-c++/common/sceneholder.cpp364
1 files changed, 364 insertions, 0 deletions
diff --git a/pacman-c++/common/sceneholder.cpp b/pacman-c++/common/sceneholder.cpp
new file mode 100644
index 0000000..bd9b01b
--- /dev/null
+++ b/pacman-c++/common/sceneholder.cpp
@@ -0,0 +1,364 @@
1#include "sceneholder.h"
2#include "constants.h"
3#include "gameentity.h"
4#include "block.h"
5#include "actor.h"
6#include "bonuspoint.h"
7#include "point.h"
8#include "util.h"
9
10SceneHolder::SceneHolder(QObject *parent)
11 : QGraphicsScene(parent), m_color(Color::none), m_pointsLeft(0)
12{
13 setSceneRect(0, 0, Constants::map_size_pixel.width, Constants::map_size_pixel.height);
14 setBackgroundBrush(Qt::black);
15
16 m_overlayText = new QGraphicsTextItem();
17
18 visualMap.resize(Constants::map_size.width);
19 for (int i = 0; i < visualMap.size(); ++i)
20 visualMap[i].resize(Constants::map_size.height);
21}
22
23void SceneHolder::reset()
24{
25 processDelayedItems();
26 showEatingText(false);
27
28 /* remove actors from scene so they don't get deleted during clear */
29 foreach(Actor *actor, m_actors)
30 {
31 actor->reset();
32 removeItem(actor);
33 }
34
35 /* clear our stuff */
36 clear();
37 m_pointsLeft = 0;
38 for (int i = 0; i < visualMap.size(); ++i)
39 {
40 visualMap[i].clear();
41 visualMap[i].resize(Constants::map_size.height);
42 }
43
44 /* add actors again */
45 foreach(Actor *actor, m_actors)
46 addItem(actor);
47}
48
49void SceneHolder::processDelayedItems()
50{
51 /* remove items that got marked for removal from scene */
52 foreach(GameEntity *item, m_oldItems)
53 {
54 removeItem(item);
55 delete item;
56 }
57 m_oldItems.clear();
58
59 /* process death */
60 foreach(const Color::Color color, m_death.keys())
61 {
62 Q_ASSERT(m_death[color] != NULL);
63 m_death[color]->onDie(m_actors[color]);
64 }
65 m_death.clear();
66}
67
68void SceneHolder::updateMap(const Transmission::map_t& map)
69{
70 processDelayedItems();
71
72 /* process update */
73 for (unsigned int x = 0; x < Constants::map_size.width; ++x)
74 {
75 for (unsigned int y = 0; y < Constants::map_size.height; ++y)
76 {
77 const Transmission::field_t &cur = map[x][y];
78 if (cur == Transmission::none)
79 continue;
80 updateMap(map, x, y);
81 }
82 }
83
84 if (m_pointsLeft == 0)
85 emit allPointsRemoved();
86}
87
88void SceneHolder::updateMap(const Transmission::map_t& map, const unsigned int x, unsigned int y)
89{
90 const Transmission::field_t &cur = map[x][y];
91 if (cur == Transmission::none)
92 return;
93
94 /* we may have multiple colors in one position (e.g during eating another pacman) */
95 Color::Color color = static_cast<Color::Color>(cur & Transmission::color_mask);
96 QList<Color::Color> colors;
97 if (color == Color::none)
98 colors.append(Color::none);
99 foreach(Color::Color col, m_eatingorder.toSet())
100 {
101 if (color & col)
102 colors.append(col);
103 }
104 Q_ASSERT(colors.count() > 0);
105
106 /* for now complain if there are more colors or it's a Transmission::death packet */
107 Q_ASSERT(colors.count() == 1 || cur & Transmission::death);
108
109 if (cur & Transmission::empty)
110 {
111 GameEntity *oldItem = visualMap[x][y];
112 /* special handling for purging field */
113 if (oldItem != NULL)
114 {
115 /* remove item from visualmap and register item for removal in next update */
116 visualMap[x][y] = NULL;
117 m_oldItems.append(oldItem);
118
119 /* an item must be removed by an actor */
120 Actor *actor = m_actors[colors.at(0)];
121 Q_ASSERT(actor != NULL);
122 oldItem->onDie(actor);
123 }
124 }
125
126 GameEntity *item = NULL;
127 if (cur == Transmission::none)
128 {
129 /* no update */
130 }
131 else
132 {
133 if (cur & Transmission::block)
134 {
135 unsigned int neighbours = Block::None;
136 /* check for old block first */
137 if (visualMap[x][y] != NULL)
138 {
139 Block *oldItem = qgraphicsitem_cast<Block *>(visualMap[x][y]);
140 if (oldItem != NULL)
141 neighbours = oldItem->neighbours();
142 }
143 /* check left side */
144 if (x > 0 && map[x - 1][y] & Transmission::block)
145 neighbours |= Block::Left;
146 /* check right side */
147 if (x < Constants::map_size.width && map[x + 1][y] & Transmission::block)
148 neighbours |= Block::Right;
149 /* check upside */
150 if (y > 0 && map[x][y - 1] & Transmission::block)
151 neighbours |= Block::Up;
152 /* check down side */
153 if (y < Constants::map_size.height && map[x][y + 1] & Transmission::block)
154 neighbours |= Block::Down;
155 item = new Block(colors.at(0), neighbours);
156 }
157
158 if (cur & Transmission::bonuspoint)
159 item = new BonusPoint();
160
161 if (cur & Transmission::point)
162 {
163 item = new Point();
164 connect(item, SIGNAL(destroyed()), this, SLOT(decrementPoints()));
165 ++m_pointsLeft;
166 }
167
168 if (cur & Transmission::pacman)
169 {
170 foreach(color, colors)
171 {
172 /* WARNING: do NOT add actor to visualMap as visualMap-items may
173 * get deleted during update and actors are referenced in_mactors too
174 * if you REALLY need that you need to changed updateMap so that all actors
175 * will be moved before any new items get allocated (totally untested)
176 */
177 Actor *actor = m_actors.value(color, NULL);
178 if (actor == NULL)
179 {
180 actor = new Actor(color, (color == m_color));
181 m_actors[color] = actor;
182 addItem(actor);
183 actor->setPos(mapPositionToCoord(x, y));
184 actor->hadReset();
185 }
186 else
187 {
188 /* check for death */
189 if (cur & Transmission::death)
190 {
191 foreach(Color::Color col, colors)
192 {
193 if (color == col)
194 continue;
195 if (m_actors[col]->canEat(actor, m_eatingorder))
196 {
197 m_death[col] = actor;
198 break;
199 }
200 }
201 }
202
203 /* move actor */
204 if (actor->hadReset())
205 actor->setPos(mapPositionToCoord(x, y));
206 else
207 actor->move(mapPositionToCoord(x, y));
208
209 /* that's kind a hack but working right now */
210 if (!(cur & Transmission::empty))
211 actor->stopEating();
212 qDebug() << "[SceneUpdate] actor moves: color=" << color
213 << "newpos=" << QPoint(x, y);
214 }
215
216 if ((cur & Transmission::death) && visualMap[x][y] != NULL)
217 m_death[color] = visualMap[x][y];
218 }
219 }
220
221 if (cur & Transmission::empty)
222 {
223 /* already handled */
224 }
225 }
226
227 /* add new created item to scene
228 * remove old item on that location if there's one
229 */
230 if (item != NULL)
231 {
232 GameEntity *oldItem = visualMap[x][y];
233 if (oldItem != NULL)
234 {
235 removeItem(oldItem);
236 delete oldItem;
237 }
238
239 addItem(item);
240 item->setPos(mapPositionToCoord(x, y));
241 visualMap[x][y] = item;
242 }
243}
244
245void SceneHolder::setColor(Color::Color color)
246{
247 m_color = color;
248}
249
250Color::Color SceneHolder::color()
251{
252 return m_color;
253}
254
255unsigned int SceneHolder::pointsLeft()
256{
257 return m_pointsLeft;
258}
259
260void SceneHolder::decrementPoints()
261{
262 --m_pointsLeft;
263}
264
265void SceneHolder::setEatingOrder(QList<Color::Color> &order)
266{
267 m_eatingorder = order;
268}
269
270QList<Color::Color> &SceneHolder::eatingOrder()
271{
272 return m_eatingorder;
273}
274
275void SceneHolder::showEatingText(bool show)
276{
277 if (!show)
278 {
279 if (m_overlayText->scene() == this)
280 removeItem(m_overlayText);
281 return;
282 }
283
284 m_overlayText->setDefaultTextColor(Qt::black);
285 QString text = QString(
286 "<div style=\"background-color: gray;\" align=\"center\">"
287 "<br />"
288 );
289 unsigned int lines = 1;
290
291 text = text % QString("<b>Your Pacman: <img src=\"%1\"/></b><br /><br />")
292 .arg(m_actors[m_color]->iconStr());
293 lines += 2;
294
295 foreach(Actor *actor, m_actors)
296 {
297 foreach(Actor *other, m_actors)
298 {
299 if (!actor->canEat(other, m_eatingorder))
300 continue;
301 text = text % QString("<img src=\"%1\"/> &nbsp;can eat <img src=\"%2\"/><br />")
302 .arg(actor->iconStr(), other->iconStr());
303 ++lines;
304 }
305 }
306 text = text % "</div>";
307 m_overlayText->setHtml(text);
308 m_overlayText->setTextWidth(150);
309 m_overlayText->setOpacity(0.9);
310
311 QFontMetrics metrics(m_overlayText->font());
312 m_overlayText->setPos((width() - m_overlayText->textWidth()) / 2, (height() - metrics.height() * lines) / 2);
313 m_overlayText->setZValue(100);
314
315 addItem(m_overlayText);
316}
317
318void SceneHolder::showWaitingForPlayers(bool show)
319{
320 if (!show)
321 {
322 if (m_overlayText->scene() == this)
323 removeItem(m_overlayText);
324 return;
325 }
326
327 m_overlayText->setDefaultTextColor(Qt::black);
328 QString text = QString(
329 "<div style=\"background-color: gray;\" align=\"center\">"
330 "<br />"
331 "Waiting for other Players...<br />"
332 "</div>"
333 );
334 unsigned int lines = 3;
335 m_overlayText->setHtml(text);
336 m_overlayText->setTextWidth(150);
337 m_overlayText->setOpacity(0.9);
338
339 QFontMetrics metrics(m_overlayText->font());
340 m_overlayText->setPos((width() - m_overlayText->textWidth()) / 2, (height() - metrics.height() * lines) / 2);
341 m_overlayText->setZValue(100);
342
343 addItem(m_overlayText);
344}
345
346QPoint SceneHolder::mapPositionToCoord(unsigned int x, unsigned int y)
347{
348 return QPoint(x * Constants::field_size.width, y * Constants::field_size.height);
349}
350
351QPoint SceneHolder::mapPositionToCoord(QPoint point)
352{
353 return mapPositionToCoord(point.x(), point.y());
354}
355
356QPoint SceneHolder::CoordToMapPosition(unsigned int x, unsigned int y)
357{
358 return QPoint(x / Constants::field_size.width, y / Constants::field_size.height);
359}
360
361QPoint SceneHolder::CoordToMapPosition(QPoint point)
362{
363 return CoordToMapPosition(point.x(), point.y());
364}