From ce48af53646cd9e7ec762fc1ac176b3aa620b11d Mon Sep 17 00:00:00 2001 From: manuel Date: Thu, 5 May 2011 00:57:07 +0200 Subject: - refactorized the whole project and made a few subprojects - replaced tcp with enet - added connect dialog - some smaller bugfixes --- pacman-c++/common/sceneholder.cpp | 364 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 364 insertions(+) create mode 100644 pacman-c++/common/sceneholder.cpp (limited to 'pacman-c++/common/sceneholder.cpp') 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 @@ +#include "sceneholder.h" +#include "constants.h" +#include "gameentity.h" +#include "block.h" +#include "actor.h" +#include "bonuspoint.h" +#include "point.h" +#include "util.h" + +SceneHolder::SceneHolder(QObject *parent) + : QGraphicsScene(parent), m_color(Color::none), m_pointsLeft(0) +{ + setSceneRect(0, 0, Constants::map_size_pixel.width, Constants::map_size_pixel.height); + setBackgroundBrush(Qt::black); + + m_overlayText = new QGraphicsTextItem(); + + visualMap.resize(Constants::map_size.width); + for (int i = 0; i < visualMap.size(); ++i) + visualMap[i].resize(Constants::map_size.height); +} + +void SceneHolder::reset() +{ + processDelayedItems(); + showEatingText(false); + + /* remove actors from scene so they don't get deleted during clear */ + foreach(Actor *actor, m_actors) + { + actor->reset(); + removeItem(actor); + } + + /* clear our stuff */ + clear(); + m_pointsLeft = 0; + for (int i = 0; i < visualMap.size(); ++i) + { + visualMap[i].clear(); + visualMap[i].resize(Constants::map_size.height); + } + + /* add actors again */ + foreach(Actor *actor, m_actors) + addItem(actor); +} + +void SceneHolder::processDelayedItems() +{ + /* remove items that got marked for removal from scene */ + foreach(GameEntity *item, m_oldItems) + { + removeItem(item); + delete item; + } + m_oldItems.clear(); + + /* process death */ + foreach(const Color::Color color, m_death.keys()) + { + Q_ASSERT(m_death[color] != NULL); + m_death[color]->onDie(m_actors[color]); + } + m_death.clear(); +} + +void SceneHolder::updateMap(const Transmission::map_t& map) +{ + processDelayedItems(); + + /* process update */ + for (unsigned int x = 0; x < Constants::map_size.width; ++x) + { + for (unsigned int y = 0; y < Constants::map_size.height; ++y) + { + const Transmission::field_t &cur = map[x][y]; + if (cur == Transmission::none) + continue; + updateMap(map, x, y); + } + } + + if (m_pointsLeft == 0) + emit allPointsRemoved(); +} + +void SceneHolder::updateMap(const Transmission::map_t& map, const unsigned int x, unsigned int y) +{ + const Transmission::field_t &cur = map[x][y]; + if (cur == Transmission::none) + return; + + /* we may have multiple colors in one position (e.g during eating another pacman) */ + Color::Color color = static_cast(cur & Transmission::color_mask); + QList colors; + if (color == Color::none) + colors.append(Color::none); + foreach(Color::Color col, m_eatingorder.toSet()) + { + if (color & col) + colors.append(col); + } + Q_ASSERT(colors.count() > 0); + + /* for now complain if there are more colors or it's a Transmission::death packet */ + Q_ASSERT(colors.count() == 1 || cur & Transmission::death); + + if (cur & Transmission::empty) + { + GameEntity *oldItem = visualMap[x][y]; + /* special handling for purging field */ + if (oldItem != NULL) + { + /* remove item from visualmap and register item for removal in next update */ + visualMap[x][y] = NULL; + m_oldItems.append(oldItem); + + /* an item must be removed by an actor */ + Actor *actor = m_actors[colors.at(0)]; + Q_ASSERT(actor != NULL); + oldItem->onDie(actor); + } + } + + GameEntity *item = NULL; + if (cur == Transmission::none) + { + /* no update */ + } + else + { + if (cur & Transmission::block) + { + unsigned int neighbours = Block::None; + /* check for old block first */ + if (visualMap[x][y] != NULL) + { + Block *oldItem = qgraphicsitem_cast(visualMap[x][y]); + if (oldItem != NULL) + neighbours = oldItem->neighbours(); + } + /* check left side */ + if (x > 0 && map[x - 1][y] & Transmission::block) + neighbours |= Block::Left; + /* check right side */ + if (x < Constants::map_size.width && map[x + 1][y] & Transmission::block) + neighbours |= Block::Right; + /* check upside */ + if (y > 0 && map[x][y - 1] & Transmission::block) + neighbours |= Block::Up; + /* check down side */ + if (y < Constants::map_size.height && map[x][y + 1] & Transmission::block) + neighbours |= Block::Down; + item = new Block(colors.at(0), neighbours); + } + + if (cur & Transmission::bonuspoint) + item = new BonusPoint(); + + if (cur & Transmission::point) + { + item = new Point(); + connect(item, SIGNAL(destroyed()), this, SLOT(decrementPoints())); + ++m_pointsLeft; + } + + if (cur & Transmission::pacman) + { + foreach(color, colors) + { + /* WARNING: do NOT add actor to visualMap as visualMap-items may + * get deleted during update and actors are referenced in_mactors too + * if you REALLY need that you need to changed updateMap so that all actors + * will be moved before any new items get allocated (totally untested) + */ + Actor *actor = m_actors.value(color, NULL); + if (actor == NULL) + { + actor = new Actor(color, (color == m_color)); + m_actors[color] = actor; + addItem(actor); + actor->setPos(mapPositionToCoord(x, y)); + actor->hadReset(); + } + else + { + /* check for death */ + if (cur & Transmission::death) + { + foreach(Color::Color col, colors) + { + if (color == col) + continue; + if (m_actors[col]->canEat(actor, m_eatingorder)) + { + m_death[col] = actor; + break; + } + } + } + + /* move actor */ + if (actor->hadReset()) + actor->setPos(mapPositionToCoord(x, y)); + else + actor->move(mapPositionToCoord(x, y)); + + /* that's kind a hack but working right now */ + if (!(cur & Transmission::empty)) + actor->stopEating(); + qDebug() << "[SceneUpdate] actor moves: color=" << color + << "newpos=" << QPoint(x, y); + } + + if ((cur & Transmission::death) && visualMap[x][y] != NULL) + m_death[color] = visualMap[x][y]; + } + } + + if (cur & Transmission::empty) + { + /* already handled */ + } + } + + /* add new created item to scene + * remove old item on that location if there's one + */ + if (item != NULL) + { + GameEntity *oldItem = visualMap[x][y]; + if (oldItem != NULL) + { + removeItem(oldItem); + delete oldItem; + } + + addItem(item); + item->setPos(mapPositionToCoord(x, y)); + visualMap[x][y] = item; + } +} + +void SceneHolder::setColor(Color::Color color) +{ + m_color = color; +} + +Color::Color SceneHolder::color() +{ + return m_color; +} + +unsigned int SceneHolder::pointsLeft() +{ + return m_pointsLeft; +} + +void SceneHolder::decrementPoints() +{ + --m_pointsLeft; +} + +void SceneHolder::setEatingOrder(QList &order) +{ + m_eatingorder = order; +} + +QList &SceneHolder::eatingOrder() +{ + return m_eatingorder; +} + +void SceneHolder::showEatingText(bool show) +{ + if (!show) + { + if (m_overlayText->scene() == this) + removeItem(m_overlayText); + return; + } + + m_overlayText->setDefaultTextColor(Qt::black); + QString text = QString( + "
" + "
" + ); + unsigned int lines = 1; + + text = text % QString("Your Pacman:

") + .arg(m_actors[m_color]->iconStr()); + lines += 2; + + foreach(Actor *actor, m_actors) + { + foreach(Actor *other, m_actors) + { + if (!actor->canEat(other, m_eatingorder)) + continue; + text = text % QString("  can eat
") + .arg(actor->iconStr(), other->iconStr()); + ++lines; + } + } + text = text % "
"; + m_overlayText->setHtml(text); + m_overlayText->setTextWidth(150); + m_overlayText->setOpacity(0.9); + + QFontMetrics metrics(m_overlayText->font()); + m_overlayText->setPos((width() - m_overlayText->textWidth()) / 2, (height() - metrics.height() * lines) / 2); + m_overlayText->setZValue(100); + + addItem(m_overlayText); +} + +void SceneHolder::showWaitingForPlayers(bool show) +{ + if (!show) + { + if (m_overlayText->scene() == this) + removeItem(m_overlayText); + return; + } + + m_overlayText->setDefaultTextColor(Qt::black); + QString text = QString( + "
" + "
" + "Waiting for other Players...
" + "
" + ); + unsigned int lines = 3; + m_overlayText->setHtml(text); + m_overlayText->setTextWidth(150); + m_overlayText->setOpacity(0.9); + + QFontMetrics metrics(m_overlayText->font()); + m_overlayText->setPos((width() - m_overlayText->textWidth()) / 2, (height() - metrics.height() * lines) / 2); + m_overlayText->setZValue(100); + + addItem(m_overlayText); +} + +QPoint SceneHolder::mapPositionToCoord(unsigned int x, unsigned int y) +{ + return QPoint(x * Constants::field_size.width, y * Constants::field_size.height); +} + +QPoint SceneHolder::mapPositionToCoord(QPoint point) +{ + return mapPositionToCoord(point.x(), point.y()); +} + +QPoint SceneHolder::CoordToMapPosition(unsigned int x, unsigned int y) +{ + return QPoint(x / Constants::field_size.width, y / Constants::field_size.height); +} + +QPoint SceneHolder::CoordToMapPosition(QPoint point) +{ + return CoordToMapPosition(point.x(), point.y()); +} -- cgit v1.2.3