From 536ddd91ae7f162045226d4b358ba95d678f6deb Mon Sep 17 00:00:00 2001 From: manuel Date: Fri, 15 Apr 2011 03:20:17 +0200 Subject: add support for random bonus points --- pacman-c++/constants.h | 10 +++ pacman-c++/sceneholder.cpp | 215 ++++++++++++++++++++++++--------------------- pacman-c++/sceneholder.h | 1 + pacman-c++/server.cpp | 50 ++++++++++- pacman-c++/server.h | 2 + pacman-c++/util.cpp | 16 ++-- pacman-c++/util.h | 2 +- 7 files changed, 185 insertions(+), 111 deletions(-) diff --git a/pacman-c++/constants.h b/pacman-c++/constants.h index a14e623..06b6561 100644 --- a/pacman-c++/constants.h +++ b/pacman-c++/constants.h @@ -27,6 +27,16 @@ namespace Constants { { const unsigned int bonus_point_value = 100; const unsigned int point_value = 10; + /* players will be placed with this minimum manhattan distance */ + const unsigned int player_minimum_distance = 5; + /* if the distance above isn't possible, decrease the distance by this value */ + const unsigned int player_distance_decr = 2; + } + + namespace Random + { + /* there's a chance of 1:20 that a bonus point will be added */ + const unsigned int bouns_point_chance = 20; } } diff --git a/pacman-c++/sceneholder.cpp b/pacman-c++/sceneholder.cpp index d9e07e5..11e0772 100644 --- a/pacman-c++/sceneholder.cpp +++ b/pacman-c++/sceneholder.cpp @@ -39,117 +39,130 @@ void SceneHolder::updateMap(const Transmission::map_t& map) const Transmission::field_t &cur = map[x][y]; if (cur == Transmission::none) continue; + updateMap(map, x, y); + } + } +} - Color::Color color = static_cast(cur & Transmission::color_mask); - GameEntity* item = NULL; +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; - 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); - } - } + Color::Color color = static_cast(cur & Transmission::color_mask); + GameEntity* item = NULL; - 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) + 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) { - Actor *actor = m_actors.value(color, NULL); - if (actor == NULL) + if (cur & tmp->color()) { - 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); - 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); + actor = tmp; + break; } } - else if (cur & Transmission::empty) - { - /* already handled */ - } - else - { - qWarning() << "Unknown data. value=" << cur; + + /* an item must be removed by an actor */ + if (actor == NULL) Q_ASSERT(false); - } + oldItem->onDie(actor); - /* add new created item to scene - * remove old item on that location if there's one + /* 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) */ - 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; - } - } + 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; } } } diff --git a/pacman-c++/sceneholder.h b/pacman-c++/sceneholder.h index 5183f65..418f16b 100644 --- a/pacman-c++/sceneholder.h +++ b/pacman-c++/sceneholder.h @@ -18,6 +18,7 @@ public: {}; unsigned int pointsLeft(); void updateMap(const Transmission::map_t& map); + void updateMap(const Transmission::map_t& map, const unsigned int x, const unsigned int y); void setColor(Color::Color color = Color::none); Color::Color color(); diff --git a/pacman-c++/server.cpp b/pacman-c++/server.cpp index a045cad..01c74c4 100644 --- a/pacman-c++/server.cpp +++ b/pacman-c++/server.cpp @@ -3,6 +3,7 @@ #include "pacman.pb.h" #include "block.h" #include "anyoption.h" +#include "bonuspoint.h" #include #include #include @@ -26,7 +27,7 @@ bool Server::run() qDebug() << "[Server] Creating map..."; Transmission::map_t map = Util::createDemoMap(); Util::placeActors(map, m_maxplayers, Color::order); - Util::makePoints(map); + Util::fillPoints(map); updateMap(map); sendUpdate(map); Util::deleteMap(map); @@ -43,6 +44,12 @@ void Server::tick() qDebug() << "[Tick] Doing server update"; Transmission::map_t map = calculateUpdates(); updateMap(map); + + /* add a random bonus point */ + QPoint pos = addRandomPoint(map, Transmission::bonuspoint); + if (!pos.isNull()) + updateMap(map, pos.x(), pos.y()); + sendUpdate(map); Util::deleteMap(map); } @@ -161,6 +168,43 @@ invalid_direction: return map; } +QPoint Server::addRandomPoint(Transmission::map_t map, Transmission::field_t type) +{ + int chance = Constants::Random::bouns_point_chance; + int rand = (int) (chance * (qrand() / (RAND_MAX + 1.0))); + if (rand != 0) + return QPoint(); + + /* get list of valid positions */ + QList validpos; + for (unsigned int x = 0; x < Constants::map_size.width; ++x) + { + for (unsigned int y = 0; y < Constants::map_size.height; ++y) + { + if (visualMap[x][y] == NULL) + validpos.append(QPoint(x, y)); + } + } + + /* remove actors possitions from list + * performance would be better if actors would be listed in visualMap too + * but this isn't possible that easily. see comment in updateMap(map) + */ + foreach (Actor *tmp, m_actors) + { + QPoint oldpos = CoordToMapPosition(tmp->pos().toPoint()); + validpos.removeAll(oldpos); + } + + if (validpos.empty()) + return QPoint(); + + rand = (int) (validpos.size() * (qrand() / (RAND_MAX + 1.0))); + QPoint pos = validpos.at(rand); + map[pos.x()][pos.y()] = type; + return pos; +} + bool Server::waitForClientConnections() { // server must stay alive as long as sockets (qt parent mem mechanism) @@ -185,14 +229,12 @@ bool Server::waitForClientConnections() QTcpSocket *socket = tcpSrv->nextPendingConnection(); connect(socket, SIGNAL(readyRead()), this, SLOT(keyPressUpdate())); - /* assign color */ + /* assign color and notify client */ Color::Color color = Color::order[i]; m_clientConnections[color] = socket; - /* notify player of color */ packet.set_color(color); packet.set_maxplayers(m_maxplayers); Util::sendPacket(packet, socket); - qDebug() << "[Connect] New Player: color=" << color; } diff --git a/pacman-c++/server.h b/pacman-c++/server.h index dac5d1c..0f2879d 100644 --- a/pacman-c++/server.h +++ b/pacman-c++/server.h @@ -34,6 +34,8 @@ protected: /* update client maps */ void sendUpdate(Transmission::map_t map); + QPoint addRandomPoint(Transmission::map_t map, Transmission::field_t type = Transmission::bonuspoint); + protected: QMap m_clientConnections; diff --git a/pacman-c++/util.cpp b/pacman-c++/util.cpp index 2a3b78a..708d005 100644 --- a/pacman-c++/util.cpp +++ b/pacman-c++/util.cpp @@ -77,7 +77,13 @@ namespace Util void placeActors(Transmission::map_t map, unsigned int players, const Color::Color *colors) { - int mindistance = 5; +#if 0 + for(unsigned int i = 0; i < players; ++i) + map[i][0] = colors[i] | Transmission::pacman | Transmission::direction_none; + return; +#endif + + int mindistance = Constants::Game::player_minimum_distance; /* this outer loop is used if there are no more valid places left * so we can change mindistance */ @@ -107,9 +113,9 @@ namespace Util int rand = (int) (validpos.size() * (qrand() / (RAND_MAX + 1.0))); QPoint newpos = validpos.at(rand); map[newpos.x()][newpos.y()] = colors[i] | Transmission::pacman | Transmission::direction_none; + qDebug() << "Actor" << i << "at" << newpos; actors.append(newpos); validpos.removeAt(rand); - qDebug() << "actor" << colors[i] << "at" << newpos; QMutableListIterator j(validpos); while(j.hasNext()) @@ -123,14 +129,14 @@ namespace Util if (validpos.empty()) { qWarning() << "There are no more valid positions for actors left on the map"; - mindistance -= 2; + mindistance -= Constants::Game::player_distance_decr; break; } } } } - void makePoints(Transmission::map_t map) + void fillPoints(Transmission::map_t map, Transmission::field_t type) { /* auto place normal points*/ for (unsigned int x = 0; x < Constants::map_size.width; ++x) @@ -139,7 +145,7 @@ namespace Util { Transmission::field_t &cur = map[x][y]; if (cur == Transmission::none) - cur |= Transmission::point; + cur = type; else if (cur == Transmission::point) cur = Transmission::none; } diff --git a/pacman-c++/util.h b/pacman-c++/util.h index a9ddbee..9812bc4 100644 --- a/pacman-c++/util.h +++ b/pacman-c++/util.h @@ -12,7 +12,7 @@ namespace Util Transmission::map_t createUninitialisedMap(); Transmission::map_t createDemoMap(); void placeActors(Transmission::map_t map, unsigned int players, const Color::Color *colors); - void makePoints(Transmission::map_t map); + void fillPoints(Transmission::map_t map, Transmission::field_t type = Transmission::point); Transmission::map_t createEmptyMap(); void deleteMap(Transmission::map_t map); -- cgit v1.2.3