diff options
| author | manuel <manuel@mausz.at> | 2011-05-05 00:57:07 +0200 |
|---|---|---|
| committer | manuel <manuel@mausz.at> | 2011-05-05 00:57:07 +0200 |
| commit | ce48af53646cd9e7ec762fc1ac176b3aa620b11d (patch) | |
| tree | f8fbf2cae8c7d0cbac2696a8f4cf94410bfb4928 /pacman-c++/common/sceneholder.cpp | |
| parent | e54ccad07e256ba877bd41d70bd358bd0085bd1e (diff) | |
| download | foop-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.cpp | 364 |
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 | |||
| 10 | SceneHolder::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 | |||
| 23 | void 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 | |||
| 49 | void 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 | |||
| 68 | void 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 | |||
| 88 | void 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 | |||
| 245 | void SceneHolder::setColor(Color::Color color) | ||
| 246 | { | ||
| 247 | m_color = color; | ||
| 248 | } | ||
| 249 | |||
| 250 | Color::Color SceneHolder::color() | ||
| 251 | { | ||
| 252 | return m_color; | ||
| 253 | } | ||
| 254 | |||
| 255 | unsigned int SceneHolder::pointsLeft() | ||
| 256 | { | ||
| 257 | return m_pointsLeft; | ||
| 258 | } | ||
| 259 | |||
| 260 | void SceneHolder::decrementPoints() | ||
| 261 | { | ||
| 262 | --m_pointsLeft; | ||
| 263 | } | ||
| 264 | |||
| 265 | void SceneHolder::setEatingOrder(QList<Color::Color> &order) | ||
| 266 | { | ||
| 267 | m_eatingorder = order; | ||
| 268 | } | ||
| 269 | |||
| 270 | QList<Color::Color> &SceneHolder::eatingOrder() | ||
| 271 | { | ||
| 272 | return m_eatingorder; | ||
| 273 | } | ||
| 274 | |||
| 275 | void 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\"/> 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 | |||
| 318 | void 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 | |||
| 346 | QPoint SceneHolder::mapPositionToCoord(unsigned int x, unsigned int y) | ||
| 347 | { | ||
| 348 | return QPoint(x * Constants::field_size.width, y * Constants::field_size.height); | ||
| 349 | } | ||
| 350 | |||
| 351 | QPoint SceneHolder::mapPositionToCoord(QPoint point) | ||
| 352 | { | ||
| 353 | return mapPositionToCoord(point.x(), point.y()); | ||
| 354 | } | ||
| 355 | |||
| 356 | QPoint SceneHolder::CoordToMapPosition(unsigned int x, unsigned int y) | ||
| 357 | { | ||
| 358 | return QPoint(x / Constants::field_size.width, y / Constants::field_size.height); | ||
| 359 | } | ||
| 360 | |||
| 361 | QPoint SceneHolder::CoordToMapPosition(QPoint point) | ||
| 362 | { | ||
| 363 | return CoordToMapPosition(point.x(), point.y()); | ||
| 364 | } | ||
