#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); visualMap.resize(Constants::map_size.width); for (int i = 0; i < visualMap.size(); ++i) visualMap[i].resize(Constants::map_size.height); } void SceneHolder::updateMap(const Transmission::map_t& map) { /* remove items that got marked for removal from scene */ QMutableListIterator i(m_oldItems); while(i.hasNext()) { i.next(); GameEntity *item = i.value(); removeItem(item); i.remove(); delete item; } /* 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); } } } 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; Color::Color color = static_cast(cur & Transmission::color_mask); GameEntity* item = NULL; if (cur & Transmission::empty) { GameEntity *oldItem = visualMap[x][y]; /* special handling for purging field * remove elements (in case it's not an actor) */ if (oldItem != NULL && dynamic_cast(oldItem) == NULL) { visualMap[x][y] = NULL; Actor *actor = NULL; foreach (Actor *tmp, m_actors) { if (cur & tmp->color()) { actor = tmp; break; } } /* an item must be removed by an actor */ if (actor == NULL) Q_ASSERT(false); oldItem->onDie(actor); /* register item for removal in next update */ m_oldItems.append(oldItem); } } if (cur == Transmission::none) { // no update } else if (cur & Transmission::block) { unsigned int neighbours = Block::None; // 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(color, neighbours); } else if (cur & Transmission::bonuspoint) item = new BonusPoint(); else if (cur & Transmission::point) { item = new Point(); connect(item, SIGNAL(destroyed()), this, SLOT(decrementPoints())); ++m_pointsLeft; } else if (cur & Transmission::pacman) { 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)); } else { Actor::Movement direction = Util::transmissionMovementToActor( cur & Transmission::direction_mask); /* 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->move(direction); /* that's kind a hack but working right now * I think that will fall on our's hat sooner or later */ if (!(cur & Transmission::empty)) actor->stopEating(); qDebug() << "[SceneUpdate] actor moves: color=" << color << "direction=" << direction << "newpos=" << QPoint(x, y); } } else if (cur & Transmission::empty) { /* already handled */ } else { qWarning() << "Unknown data. value=" << cur; Q_ASSERT(false); } /* add new created item to scene * remove old item on that location if there's one */ if (item != NULL) { addItem(item); item->setPos(mapPositionToCoord(x, y)); GameEntity *oldItem = visualMap[x][y]; visualMap[x][y] = item; if (oldItem != NULL) { removeItem(item); delete oldItem; } } } 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; } 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()); }