From 41a31420cf091aeb4e986503387855d41e550106 Mon Sep 17 00:00:00 2001 From: manuel Date: Mon, 25 Apr 2011 14:39:00 +0200 Subject: - add intro sound on every round - add dieing sound - add dieing animation - add die on moving onto colorized block --- pacman-c++/actor.cpp | 49 ++++++++++++++-- pacman-c++/actor.h | 7 ++- pacman-c++/audio.cpp | 54 +++++++++++------ pacman-c++/audio.h | 9 ++- pacman-c++/block.cpp | 19 +++--- pacman-c++/block.h | 3 +- pacman-c++/bonuspoint.cpp | 5 +- pacman-c++/bonuspoint.h | 2 +- pacman-c++/constants.h | 9 +-- pacman-c++/gameentity.cpp | 4 +- pacman-c++/gameentity.h | 20 +++---- pacman-c++/mainwidget.cpp | 29 ++++----- pacman-c++/mainwidget.h | 1 + pacman-c++/pics/actor1.png | Bin 796 -> 1231 bytes pacman-c++/pics/actor2.png | Bin 805 -> 1257 bytes pacman-c++/pics/actor3.png | Bin 793 -> 1226 bytes pacman-c++/pics/actor4.png | Bin 804 -> 1536 bytes pacman-c++/point.cpp | 5 +- pacman-c++/point.h | 2 +- pacman-c++/sceneholder.cpp | 76 ++++++++++++++---------- pacman-c++/sceneholder.h | 4 +- pacman-c++/server.cpp | 143 ++++++++++++++++++++++++++++----------------- pacman-c++/server.h | 9 ++- 23 files changed, 286 insertions(+), 164 deletions(-) (limited to 'pacman-c++') diff --git a/pacman-c++/actor.cpp b/pacman-c++/actor.cpp index c8922f7..2dced34 100644 --- a/pacman-c++/actor.cpp +++ b/pacman-c++/actor.cpp @@ -57,6 +57,29 @@ Actor::Actor(Color::Color color, bool local, QGraphicsItem *parent) m_eating.append(setupEatingAnimation(Actor::Up)); m_eating.append(setupEatingAnimation(Actor::Down)); + /* dieing animation */ + m_dieing = new QSequentialAnimationGroup(this); + for (int i = 0; i < 11; i++) + { + PixmapItem *img = new PixmapItem(m_pix, this); + m_images.append(img); + int x = i * Constants::sprite_offset + Constants::sprite_margin; + int y = 5 * Constants::sprite_offset + Constants::sprite_margin; + img->setSprite(x, y, Constants::field_size.width, Constants::field_size.height); + img->setZValue(zValue()); + img->setVisible(false); + + QPropertyAnimation *fadein = new QPropertyAnimation(img, "visible", m_dieing); + fadein->setDuration(0); + fadein->setEndValue(true); + + m_dieing->addPause(130); + + QPropertyAnimation *fadeout = new QPropertyAnimation(img, "visible", m_dieing); + fadeout->setDuration(0); + fadeout->setEndValue(false); + } + /* setup waka sound */ if (local) m_wakaPlayer = new GaplessAudioPlayer(Sound::WakaWaka, 100, this); @@ -112,11 +135,21 @@ bool Actor::isLocal() return m_local; } -void Actor::resetDirection() +void Actor::resetAnimation() { + if (Constants::server) + return; + + stopEating(); + m_moving->stop(); + m_dieing->stop(); /* hide all pictures */ for (int i = 0; i < m_images.size(); ++i) m_images.at(i)->setVisible(false); + + if (m_eating[m_direction] != NULL) + m_eating[m_direction]->stop(); + m_direction = Actor::None; m_images[m_direction]->setVisible(true); } @@ -213,9 +246,14 @@ bool Actor::canEat(Actor *other, const QList &order) void Actor::die() { - if (!m_local) + if (Constants::server) return; - AudioManager::self()->play(Sound::Die); + + resetAnimation(); + m_images[m_direction]->setVisible(false); + m_dieing->start(); + if (m_local) + AudioManager::self()->play(Sound::Die); } void Actor::eatingFruit() @@ -261,9 +299,10 @@ void Actor::addRoundPoints(unsigned int amount) m_roundPoints += amount; } -void Actor::finishRound() +void Actor::finishRound(bool died) { - m_gamePoints += m_roundPoints; + if (!died) + m_gamePoints += m_roundPoints; m_roundPoints = 0; } diff --git a/pacman-c++/actor.h b/pacman-c++/actor.h index 389d7c6..eb04c71 100644 --- a/pacman-c++/actor.h +++ b/pacman-c++/actor.h @@ -16,7 +16,7 @@ Q_OBJECT public: enum Movement { - None = 0, + None = 0, Left, Right, Up, @@ -34,7 +34,7 @@ public: PixmapItem &icon(); Movement direction(); - void resetDirection(); + void resetAnimation(); bool isLocal(); void move(Movement direction); bool isMoving(); @@ -48,7 +48,7 @@ public: unsigned int getRoundPoints(); unsigned int getGamePoints(); void addRoundPoints(unsigned int amount); - void finishRound(); + void finishRound(bool died = false); static QPoint movementToPoint(const Actor::Movement direction); @@ -69,6 +69,7 @@ private: QList m_images; QList m_eating; QParallelAnimationGroup *m_moving; + QSequentialAnimationGroup *m_dieing; }; #endif // ACTOR_H diff --git a/pacman-c++/audio.cpp b/pacman-c++/audio.cpp index d627c75..5fb4416 100644 --- a/pacman-c++/audio.cpp +++ b/pacman-c++/audio.cpp @@ -15,18 +15,19 @@ AudioManager::AudioManager() : m_muted(true) { if (Constants::server) + { qDebug() << "Server has no sound"; + m_players.append(new AudioPlayer(this)); + } else { preload(); - AudioPlayer *firstplayer = new AudioPlayer(this); firstplayer->test(m_sounds[Sound::WakaWaka]); m_working = firstplayer->m_working; m_players.append(firstplayer); - - m_muted = false; } + m_muted = false; } AudioManager *AudioManager::self() @@ -97,15 +98,9 @@ AudioPlayer *AudioManager::audioPlayer() return m_players.at(0); } -void AudioManager::play(Sound::Type sound) +void AudioManager::play(Sound::Type sound, bool wait) { - if (!isWorking()) - { - emit audioPlayer()->finished(); - return; - } - - audioPlayer()->play(sound); + audioPlayer()->play(sound, wait); } void AudioManager::enqueue(Sound::Type sound) @@ -151,11 +146,14 @@ QFile *AudioManager::sound(Sound::Type sound) /* --------------------------------------------------------------- */ AudioPlayer::AudioPlayer(QObject *parent) - : Phonon::MediaObject(parent) + : Phonon::MediaObject(parent), m_working(false) { - m_working = AudioManager::m_working; - m_output = new Phonon::AudioOutput(Phonon::MusicCategory, this); - Phonon::createPath(this, m_output); + if (!Constants::server) + { + m_working = AudioManager::m_working; + m_output = new Phonon::AudioOutput(Phonon::MusicCategory, this); + Phonon::createPath(this, m_output); + } } bool AudioPlayer::isWorking() const @@ -200,10 +198,25 @@ void AudioPlayer::play() Phonon::MediaObject::play(); } -void AudioPlayer::play(Sound::Type sound) +void AudioPlayer::play(Sound::Type sound, bool wait) { - setCurrentSource(Phonon::MediaSource(AudioManager::self()->sound(sound))); - play(); + if (m_working) + { + setCurrentSource(Phonon::MediaSource(AudioManager::self()->sound(sound))); + play(); + } + else if (wait) + { + QTimer *timer = new QTimer(this); + timer->setSingleShot(true); + unsigned int interval = Sound::length[sound]; + /* add a small delay server side only */ + if (Constants::server) + interval += Constants::tick; + timer->setInterval(interval); + connect(timer, SIGNAL(timeout()), this, SLOT(finished_ex())); + timer->start(); + } } /* this is a simple hack to check if phonon can actually play sounds.. */ @@ -227,6 +240,11 @@ void AudioPlayer::test(QFile *testsound) clear(); } +void AudioPlayer::finished_ex() +{ + emit finished(); +} + void AudioPlayer::stateChanged_ex(Phonon::State newstate, Phonon::State /* oldstate */) { if (newstate != Phonon::ErrorState) diff --git a/pacman-c++/audio.h b/pacman-c++/audio.h index 3e76f50..9a4feec 100644 --- a/pacman-c++/audio.h +++ b/pacman-c++/audio.h @@ -23,6 +23,10 @@ namespace Sound Die, Ambient }; + + const unsigned int length[] = { + 4310, 2090, 570, 570, 1720 + }; }; /* --------------------------------------------------------------- */ @@ -50,7 +54,7 @@ public: bool isMuted() const; void setLoop(Sound::Type sound); void play(); - void play(Sound::Type sound); + void play(Sound::Type sound, bool wait = false); protected: void test(QFile *testsound); @@ -60,6 +64,7 @@ public slots: void loopEnqueue(); protected slots: + void finished_ex(); void testFinished(); void stateChanged_ex(Phonon::State newstate, Phonon::State oldstate); @@ -116,7 +121,7 @@ public: void clearQueue() const; AudioPlayer *audioPlayer(); - void play(Sound::Type sound); + void play(Sound::Type sound, bool wait = false); void enqueue(Sound::Type sound); void registerAudioPlayer(AudioPlayer *player); diff --git a/pacman-c++/block.cpp b/pacman-c++/block.cpp index 68dd735..7f9dd14 100644 --- a/pacman-c++/block.cpp +++ b/pacman-c++/block.cpp @@ -36,18 +36,21 @@ void Block::setNeighbours(unsigned int neighbours) setSprite(neighbours * Constants::sprite_offset, 0, Constants::field_size.width, Constants::field_size.height); } -bool Block::checkEnter(Actor *actor) +bool Block::checkEnter(Actor * /* actor */) { if (m_color == Color::none) return false; - return (m_color == actor->color()); + return true; } -bool Block::enter(Actor *actor) +GameEntity::EnteredState Block::enter(Actor *actor) { - if (m_color != actor->color()) - { - //TODO: actor dies + game ends - } - return true; + if (m_color != Color::none && m_color != actor->color()) + return DestroyedActor; + return Nothing; +} + +void Block::onDie(Actor *actor) +{ + actor->die(); } diff --git a/pacman-c++/block.h b/pacman-c++/block.h index 2e47646..abfbc5a 100644 --- a/pacman-c++/block.h +++ b/pacman-c++/block.h @@ -31,7 +31,8 @@ public: unsigned int neighbours(); void setNeighbours(unsigned int neighbours); virtual bool checkEnter(Actor *actor); - virtual bool enter(Actor *actor); + virtual EnteredState enter(Actor *actor); + virtual void onDie(Actor *); private: // map for saving QPixmaps for reuse diff --git a/pacman-c++/bonuspoint.cpp b/pacman-c++/bonuspoint.cpp index c90cccc..a6736c4 100644 --- a/pacman-c++/bonuspoint.cpp +++ b/pacman-c++/bonuspoint.cpp @@ -26,11 +26,10 @@ BonusPoint::BonusPoint(QGraphicsItem *parent) setSprite(rand * 20 + Constants::sprite_margin, Constants::sprite_margin, Constants::field_size.width, Constants::field_size.height); } -bool BonusPoint::enter(Actor *actor) +GameEntity::EnteredState BonusPoint::enter(Actor *actor) { actor->addRoundPoints(Constants::Game::bonus_point_value); - m_eaten = true; - return false; + return DestroyedEntity; } void BonusPoint::onDie(Actor *actor) diff --git a/pacman-c++/bonuspoint.h b/pacman-c++/bonuspoint.h index fbb5ba2..a72a4db 100644 --- a/pacman-c++/bonuspoint.h +++ b/pacman-c++/bonuspoint.h @@ -17,7 +17,7 @@ public: virtual ~BonusPoint() {}; - virtual bool enter(Actor *actor); + virtual EnteredState enter(Actor *actor); virtual void onDie(Actor *actor); }; diff --git a/pacman-c++/constants.h b/pacman-c++/constants.h index f9f40f9..e7dedbf 100644 --- a/pacman-c++/constants.h +++ b/pacman-c++/constants.h @@ -83,12 +83,13 @@ namespace Transmission const field_t bonuspoint = (1 << 6); const field_t pacman = (1 << 7); const field_t empty = (1 << 8); // explicit empty for update + const field_t death = (1 << 9); const field_t direction_none = 0; - const field_t direction_left = (1 << 9); - const field_t direction_right = (1 << 10); - const field_t direction_up = (1 << 11); - const field_t direction_down = (1 << 12); + const field_t direction_left = (1 << 10); + const field_t direction_right = (1 << 11); + const field_t direction_up = (1 << 12); + const field_t direction_down = (1 << 13); const mask_t color_mask = Color::none | Color::red | Color::blue | Color::green | Color::yellow; const mask_t type_mask = block | bonuspoint; diff --git a/pacman-c++/gameentity.cpp b/pacman-c++/gameentity.cpp index 156deda..e73e759 100644 --- a/pacman-c++/gameentity.cpp +++ b/pacman-c++/gameentity.cpp @@ -1,9 +1,9 @@ #include "gameentity.h" GameEntity::GameEntity(Color::Color color, QGraphicsItem *parent) - : PixmapItem(parent), m_type(Type), m_eaten(false), m_color(color) + : PixmapItem(parent), m_type(Type), m_color(color) {} GameEntity::GameEntity(QGraphicsItem *parent) - : PixmapItem(parent), m_type(Type), m_eaten(false), m_color(Color::none) + : PixmapItem(parent), m_type(Type), m_color(Color::none) {} diff --git a/pacman-c++/gameentity.h b/pacman-c++/gameentity.h index 92b485e..116fae5 100644 --- a/pacman-c++/gameentity.h +++ b/pacman-c++/gameentity.h @@ -20,6 +20,13 @@ public: Type = UserType + 1 }; + enum EnteredState + { + Nothing, + DestroyedEntity, + DestroyedActor + }; + public: GameEntity(Color::Color color = Color::none, QGraphicsItem *parent = 0); GameEntity(QGraphicsItem *parent); @@ -41,18 +48,10 @@ public: /* performs action when this actor acctually enters * returns whether this entity survives the entering */ - virtual bool enter(Actor *) + virtual EnteredState enter(Actor *) { /* default to no action/survive */ - return true; - } - - /* check whether this entity is regarded as eaten - * (and can be removed in the next tick) - */ - virtual bool eaten() - { - return m_eaten; + return Nothing; } /* called when an instance acctually dies for creating effects */ @@ -67,7 +66,6 @@ public: protected: int m_type; - bool m_eaten; Color::Color m_color; }; diff --git a/pacman-c++/mainwidget.cpp b/pacman-c++/mainwidget.cpp index eb032bd..f164219 100644 --- a/pacman-c++/mainwidget.cpp +++ b/pacman-c++/mainwidget.cpp @@ -33,13 +33,8 @@ MainWidget::MainWidget(QWidget *parent) m_socket->waitForReadyRead(); tick(); - connect(m_socket, SIGNAL(readyRead()), this, SLOT(tick())); qDebug() << "[Connect] mycolor=" << m_scene->color(); - - //TODO: play intro as soon as there are enough players - //connect(AudioPlayer::self(), SIGNAL(finished()), this, SLOT(startGame())); - //AudioPlayer::self()->play(AudioPlayer::Intro); - startGame(); + connect(m_socket, SIGNAL(readyRead()), this, SLOT(tick())); } bool MainWidget::connected() @@ -146,6 +141,7 @@ void MainWidget::tick() Q_ASSERT(worked); Q_UNUSED(worked); + /* eating order data set inidicates a new round */ if (m_updatepacket.eating_order_size() > 0) { Q_ASSERT(m_scene != NULL); @@ -156,6 +152,11 @@ void MainWidget::tick() for(int i = 0; i < m_updatepacket.eating_order_size(); ++i) order.append(static_cast(m_updatepacket.eating_order(i) & Transmission::color_mask)); m_scene->setEatingOrder(order); + + /* stop and restart game */ + stopGame(); + connect(AudioManager::self()->audioPlayer(), SIGNAL(finished()), this, SLOT(startGame())); + AudioManager::self()->play(Sound::Intro, true); } Transmission::map_t map = Util::createUninitialisedMap(); @@ -177,8 +178,6 @@ void MainWidget::tick() void MainWidget::keyPressEvent(QKeyEvent* event) { - if (!m_running) - return; if (event->isAutoRepeat()) return; @@ -194,8 +193,6 @@ void MainWidget::keyPressEvent(QKeyEvent* event) void MainWidget::sendKeyUpdate() { - if (!m_running) - return; if (m_currentKey == Transmission::direction_none) return; qDebug() << "[SendKey] key=" << m_currentKey; @@ -206,10 +203,8 @@ void MainWidget::sendKeyUpdate() void MainWidget::keyReleaseEvent(QKeyEvent* event) { - if (!m_running) - return; if (event->isAutoRepeat()) - return; + return; QWidget::keyReleaseEvent(event); m_currentKey = Transmission::none; @@ -218,10 +213,18 @@ void MainWidget::keyReleaseEvent(QKeyEvent* event) void MainWidget::startGame() { + disconnect(AudioManager::self()->audioPlayer(), NULL, this, SLOT(startGame())); m_running = true; + sendKeyUpdate(); m_ambientPlayer->play(); } +void MainWidget::stopGame() +{ + m_running = false; + m_ambientPlayer->pause(); +} + void MainWidget::setAmbientMuted(bool muted) { m_ambientPlayer->setMuted(muted); diff --git a/pacman-c++/mainwidget.h b/pacman-c++/mainwidget.h index ef282c1..d5695ed 100644 --- a/pacman-c++/mainwidget.h +++ b/pacman-c++/mainwidget.h @@ -28,6 +28,7 @@ protected: private slots: void startGame(); + void stopGame(); void playerScoreClicked(); void tick(); void sendKeyUpdate(); diff --git a/pacman-c++/pics/actor1.png b/pacman-c++/pics/actor1.png index ae9f172..5a37b4f 100644 Binary files a/pacman-c++/pics/actor1.png and b/pacman-c++/pics/actor1.png differ diff --git a/pacman-c++/pics/actor2.png b/pacman-c++/pics/actor2.png index 07ecb3f..736a6e7 100644 Binary files a/pacman-c++/pics/actor2.png and b/pacman-c++/pics/actor2.png differ diff --git a/pacman-c++/pics/actor3.png b/pacman-c++/pics/actor3.png index 486fd37..f963cff 100644 Binary files a/pacman-c++/pics/actor3.png and b/pacman-c++/pics/actor3.png differ diff --git a/pacman-c++/pics/actor4.png b/pacman-c++/pics/actor4.png index 9684fc0..e500dc5 100644 Binary files a/pacman-c++/pics/actor4.png and b/pacman-c++/pics/actor4.png differ diff --git a/pacman-c++/point.cpp b/pacman-c++/point.cpp index 2257b12..d7ebdb1 100644 --- a/pacman-c++/point.cpp +++ b/pacman-c++/point.cpp @@ -21,11 +21,10 @@ Point::Point(QGraphicsItem *parent) setPixmap(*pixmap); } -bool Point::enter(Actor *actor) +GameEntity::EnteredState Point::enter(Actor *actor) { actor->addRoundPoints(Constants::Game::point_value); - m_eaten = true; - return false; + return DestroyedEntity; } void Point::onDie(Actor *actor) diff --git a/pacman-c++/point.h b/pacman-c++/point.h index a406194..7739554 100644 --- a/pacman-c++/point.h +++ b/pacman-c++/point.h @@ -17,7 +17,7 @@ public: virtual ~Point() {}; - virtual bool enter(Actor *actor); + virtual EnteredState enter(Actor *actor); virtual void onDie(Actor *actor); }; diff --git a/pacman-c++/sceneholder.cpp b/pacman-c++/sceneholder.cpp index 56e0fff..1ecf31b 100644 --- a/pacman-c++/sceneholder.cpp +++ b/pacman-c++/sceneholder.cpp @@ -20,23 +20,51 @@ SceneHolder::SceneHolder(QObject *parent) void SceneHolder::reset() { - /* reset actor directions */ + processDelayedItems(); + + /* remove actors from scene so they don't get deleted during clear */ foreach(Actor *actor, m_actors) - actor->resetDirection(); + { + actor->resetAnimation(); + 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::updateMap(const Transmission::map_t& map) +void SceneHolder::processDelayedItems() { /* remove items that got marked for removal from scene */ - QMutableListIterator i(m_oldItems); - while(i.hasNext()) + foreach(GameEntity *item, m_oldItems) { - i.next(); - GameEntity *item = i.value(); removeItem(item); - i.remove(); 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) @@ -66,28 +94,18 @@ void SceneHolder::updateMap(const Transmission::map_t& map, const unsigned int x if (cur & Transmission::empty) { GameEntity *oldItem = visualMap[x][y]; - /* special handling for purging field - */ + /* special handling for purging field */ if (oldItem != NULL) { + /* remove item from visualmap and register item for removal in next update */ visualMap[x][y] = NULL; - Actor *actor = NULL; - foreach (Actor *tmp, m_actors) - { - if (cur & tmp->color()) - { - actor = tmp; - break; - } - } + m_oldItems.append(oldItem); /* an item must be removed by an actor */ + Actor *actor = m_actors[color]; if (actor == NULL) Q_ASSERT(false); oldItem->onDie(actor); - - /* register item for removal in next update */ - m_oldItems.append(oldItem); } } @@ -165,6 +183,10 @@ void SceneHolder::updateMap(const Transmission::map_t& map, const unsigned int x qDebug() << "[SceneUpdate] actor moves: color=" << color << "direction=" << direction << "newpos=" << QPoint(x, y); } + + + if (cur & Transmission::death) + m_death[color] = visualMap[x][y]; } if (cur & Transmission::empty) @@ -221,16 +243,6 @@ QList &SceneHolder::eatingOrder() return m_eatingorder; } -void SceneHolder::removeActors() -{ - foreach(Actor *actor, m_actors) - { - removeItem(actor); - delete actor; - } - m_actors.clear(); -} - QPoint SceneHolder::mapPositionToCoord(unsigned int x, unsigned int y) { return QPoint(x * Constants::field_size.width, y * Constants::field_size.height); diff --git a/pacman-c++/sceneholder.h b/pacman-c++/sceneholder.h index 9340850..f36c31e 100644 --- a/pacman-c++/sceneholder.h +++ b/pacman-c++/sceneholder.h @@ -24,7 +24,6 @@ public: Color::Color color(); void setEatingOrder(QList &order); QList &eatingOrder(); - void removeActors(); signals: void allPointsRemoved(); @@ -33,6 +32,8 @@ private slots: void decrementPoints(); protected: + /* process items that got delayed by one tick */ + void processDelayedItems(); /* data conversion */ QPoint mapPositionToCoord(unsigned int x, unsigned int y); QPoint mapPositionToCoord(QPoint point); @@ -50,6 +51,7 @@ protected: * must be remove one tick later */ QList m_oldItems; + QMap m_death; /* my local color */ Color::Color m_color; diff --git a/pacman-c++/server.cpp b/pacman-c++/server.cpp index be45a66..ef271f0 100644 --- a/pacman-c++/server.cpp +++ b/pacman-c++/server.cpp @@ -8,11 +8,12 @@ #include #include #include +#include Server::Server(QWidget *parent) : SceneHolder(parent), m_bindaddress(QHostAddress::Any), m_port(Constants::Networking::port), m_numbots(0), - m_rounds(3), m_curRound(0), m_roundFinished(false) + m_rounds(3), m_curRound(0), m_running(false), m_finishRound(false) { /* determine max players by using order array */ for(m_maxplayers = 0; Color::order[m_maxplayers] != Color::none; ++m_maxplayers); @@ -36,54 +37,43 @@ bool Server::run() if (!waitForClientConnections()) return false; - connect(this, SIGNAL(allPointsRemoved()), this, SLOT(setRoundFinished())); + connect(this, SIGNAL(allPointsRemoved()), this, SLOT(setFinishRound())); initRoundMap(); return true; } void Server::tick() { - //qDebug() << "[Tick] Doing server update"; - if (m_roundFinished) + qDebug() << "[Tick] Doing server update"; + if (m_finishRound) + stopGame(true); + if (!m_running) { - // TODO: call this when a pacman get's eaten - /* first finish previous round */ - foreach(Actor *actor, m_actors) - actor->finishRound(); - - ++m_curRound; - if(m_curRound < m_rounds) - initRoundMap(); - else - { - /* end of game */ - qDebug() << "All round finished. Exiting..."; - m_tickTimer->stop(); - qApp->quit(); - } + Transmission::map_t map = Util::createEmptyMap(); + sendUpdate(map); + Util::deleteMap(map); + return; } - else - { - /* let the bots move */ - foreach (Color::Color color, m_bots) - botCalculate(m_actors[color]); - /* move on the virtual map */ - Transmission::map_t map = calculateUpdates(); - updateMap(map); + /* let the bots move */ + foreach (Color::Color color, m_bots) + botCalculate(m_actors[color]); - /* add a random bonus point */ - QPoint pos = addRandomPoint(map, Transmission::bonuspoint); - if (!pos.isNull()) - updateMap(map, pos.x(), pos.y()); + /* move on the virtual map */ + Transmission::map_t map = calculateUpdates(); + updateMap(map); - /* add/remove random colorized block */ - if (this->property("coloredblocks").toBool()) - colorizeBlocks(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); - } + /* add/remove random colorized block */ + if (this->property("coloredblocks").toBool()) + colorizeBlocks(map); + + sendUpdate(map); + Util::deleteMap(map); } Transmission::map_t Server::calculateUpdates() @@ -94,14 +84,15 @@ Transmission::map_t Server::calculateUpdates() while (i.hasNext()) { i.next(); - Actor *actor = m_actors.value(i.key()); + Color::Color color = i.key(); + Actor *actor = m_actors[color]; QPoint mapPosition = CoordToMapPosition(actor->pos().toPoint()); Actor::Movement direction = i.value(); int turn = 0; invalid_direction: ++turn; - qDebug() << "[Calc] Actor wants to move: color=" << i.key() + qDebug() << "[Calc] Actor wants to move: color=" << color << "pos=" << mapPosition << "direction=" << direction; QPoint newMapPosition = mapPosition + Actor::movementToPoint(direction); @@ -132,10 +123,15 @@ invalid_direction: else { /* apply actions of entering this field */ - bool survive = item->enter(actor); - if (!survive) - { + GameEntity::EnteredState survive = item->enter(actor); + if (survive == GameEntity::DestroyedEntity) map[newMapPosition.x()][newMapPosition.y()] = Transmission::empty | actor->color(); + else if (survive == GameEntity::DestroyedActor) + { + m_actors[item->color()]->addRoundPoints(actor->getRoundPoints()); + actor->finishRound(true); + map[newMapPosition.x()][newMapPosition.y()] = Transmission::death | actor->color(); + setFinishRound(); } } } @@ -161,7 +157,7 @@ invalid_direction: } map[newMapPosition.x()][newMapPosition.y()] |= Transmission::pacman | - i.key() | Util::actorMovementToTransmission(direction); + color | Util::actorMovementToTransmission(direction); /* DEBUG: uncomments to disable auto-movement */ //direction = Actor::None; @@ -169,7 +165,7 @@ invalid_direction: if (direction == Actor::None) { /* set actor to non-moving */ - m_actorMovements[i.key()] = Actor::None; + m_actorMovements[color] = Actor::None; i.remove(); } } @@ -228,11 +224,12 @@ void Server::colorizeBlocks(Transmission::map_t map) i.setValue(--val); else { + QPoint block = i.key(); /* check for actor collision */ bool skip = false; foreach (Actor *actor, m_actors) { - if (CoordToMapPosition(actor->pos().toPoint()) == i.key()) + if (CoordToMapPosition(actor->pos().toPoint()) == block) skip = true; if (skip) break; @@ -240,7 +237,6 @@ void Server::colorizeBlocks(Transmission::map_t map) if (skip) continue; - QPoint block = i.key(); map[block.x()][block.y()] |= Transmission::block | Color::none; updateMap(map, block.x(), block.y()); m_blocks.append(block); @@ -510,16 +506,14 @@ void Server::keyPressUpdate() } } -void Server::setRoundFinished(bool value) -{ - m_roundFinished = value; -} - void Server::initRoundMap() { qDebug() << "[initRoundMap] New round starts..."; m_tickTimer->stop(); + /* reset scene and clean up items */ + reset(); + /* create new map */ Transmission::map_t map = Util::createDemoMap(); Util::placeActors(map, m_maxplayers, Color::order); @@ -542,11 +536,54 @@ void Server::initRoundMap() Util::deleteMap(map); map = NULL; - m_roundFinished = false; m_actorMovements.clear(); + + disconnect(AudioManager::self()->audioPlayer(), NULL, this, NULL); + connect(AudioManager::self()->audioPlayer(), SIGNAL(finished()), this, SLOT(startGame())); + AudioManager::self()->play(Sound::Intro, true); m_tickTimer->start(); } +void Server::startGame() +{ + m_running = true; +} + +void Server::stopGame(bool delay) +{ + /* first finish previous round */ + foreach(Actor *actor, m_actors) + actor->finishRound(); + m_finishRound = false; + m_running = false; + + /* add delay if requested */ + if (delay) + { + disconnect(AudioManager::self()->audioPlayer(), NULL, this, NULL); + connect(AudioManager::self()->audioPlayer(), SIGNAL(finished()), this, SLOT(stopGame())); + AudioManager::self()->play(Sound::Die, true); + return; + } + + /* do next-round work */ + ++m_curRound; + if(m_rounds == 0 || m_curRound < m_rounds) + initRoundMap(); + else + { + /* end of game */ + qDebug() << "All round finished. Exiting..."; + qApp->quit(); + } +} + + +void Server::setFinishRound() +{ + m_finishRound = true; +} + bool Server::parseCommandline() { AnyOption opt; @@ -583,7 +620,7 @@ bool Server::parseCommandline() << " Disable random colorized blocks" << endl << endl; opt.setOption("rounds", 'r'); - out << " -r, --rounds [1..n]" << endl + out << " -r, --rounds [0 | 1..n]" << endl << " Number of rounds to play" << endl << " Default: " << m_rounds << endl << endl; diff --git a/pacman-c++/server.h b/pacman-c++/server.h index a5afbfe..41b800e 100644 --- a/pacman-c++/server.h +++ b/pacman-c++/server.h @@ -40,8 +40,10 @@ protected: void initRoundMap(); protected slots: - /* called when a round is finished */ - void setRoundFinished(bool value = true); + /* called when a round is started/finished */ + void startGame(); + void stopGame(bool delay = false); + void setFinishRound(); protected: QMap m_clientConnections; @@ -66,7 +68,8 @@ protected: unsigned int m_rounds; /* current round, starting at 0 */ unsigned int m_curRound; - bool m_roundFinished; + bool m_running; + bool m_finishRound; QTimer *m_tickTimer; -- cgit v1.2.3