From ca29fc0babe8fc985a9e4656f80fc7faec4ac8a5 Mon Sep 17 00:00:00 2001 From: manuel Date: Wed, 11 May 2011 17:38:29 +0200 Subject: - fix audio plugin and make that a real interface - that fixes a duplicate statis audiomanager (1x pacman, 1x audio plugin) on windows - display won/lost dialog upon gameend --- pacman-c++/client/client.cpp | 14 ++-- pacman-c++/client/mainwidget.cpp | 95 +++++++++++++++++++-------- pacman-c++/client/mainwidget.h | 7 +- pacman-c++/common.pri | 4 -- pacman-c++/common/actor.cpp | 6 +- pacman-c++/common/audio.cpp | 109 ++++++++++++++++++++----------- pacman-c++/common/audio.h | 96 ++++++--------------------- pacman-c++/common/audiointerface.h | 60 +++++++++++++++++ pacman-c++/common/common.pro | 3 +- pacman-c++/common/constants.h | 1 + pacman-c++/common/sceneholder.cpp | 60 ++++++++++------- pacman-c++/common/sceneholder.h | 8 ++- pacman-c++/phononplayer/phononplayer.cpp | 37 ++++++++--- pacman-c++/phononplayer/phononplayer.h | 14 ++-- pacman-c++/phononplayer/phononplayer.pro | 3 +- pacman-c++/proto/pacman.proto | 4 +- pacman-c++/server/server.cpp | 39 ++++++----- pacman-c++/server/server.h | 6 +- 18 files changed, 344 insertions(+), 222 deletions(-) create mode 100644 pacman-c++/common/audiointerface.h (limited to 'pacman-c++') diff --git a/pacman-c++/client/client.cpp b/pacman-c++/client/client.cpp index a00249b..d20e6bf 100644 --- a/pacman-c++/client/client.cpp +++ b/pacman-c++/client/client.cpp @@ -9,16 +9,14 @@ extern "C" { } Client::Client() - : m_ambientMuted(false) + : m_dialog(NULL), m_ambientMuted(false) { m_settings = new QSettings(qApp->organizationName(), qApp->applicationName(), this); - m_dialog = new QDialog(this); m_mainWidget = new MainWidget(this); createMenu(); m_mainWidget->setAmbientMuted(m_ambientMuted); setCentralWidget(m_mainWidget); showConnectDialog(); - m_dialog->setFocus(); } void Client::createMenu() @@ -81,6 +79,7 @@ void Client::createMenu() disconnectAction->setDisabled(true); fileMenu->addAction(disconnectAction); connect(disconnectAction, SIGNAL(triggered()), m_mainWidget, SLOT(doDisconnect())); + connect(disconnectAction, SIGNAL(triggered()), m_mainWidget, SLOT(deleteGUI())); connect(m_mainWidget, SIGNAL(connected(bool)), disconnectAction, SLOT(setEnabled(bool))); /* exit entry */ @@ -134,10 +133,8 @@ QPixmap Client::soundIcon(bool enabled) const void Client::showAbout() { if (m_dialog != NULL) - { delete m_dialog; - m_dialog = new QDialog(this); - } + m_dialog = new QDialog(this); m_dialog->setWindowTitle("About Pacman"); m_dialog->setWindowFlags(m_dialog->windowFlags() & ~Qt::WindowContextHelpButtonHint); @@ -176,10 +173,9 @@ void Client::showAbout() void Client::showConnectDialog() { if (m_dialog != NULL) - { delete m_dialog; - m_dialog = new QDialog(this); - } + m_dialog = new QDialog(this); + m_dialog->setModal(true); m_dialog->setWindowTitle("Connect"); QGridLayout *layout = new QGridLayout(m_dialog); diff --git a/pacman-c++/client/mainwidget.cpp b/pacman-c++/client/mainwidget.cpp index f2e3f46..99b0f5b 100644 --- a/pacman-c++/client/mainwidget.cpp +++ b/pacman-c++/client/mainwidget.cpp @@ -22,13 +22,14 @@ MainWidget::MainWidget(QWidget *parent) m_ambientPlayer = new GaplessAudioPlayer(Sound::Ambient, 100, this); m_recvTimer = new QTimer(this); - m_recvTimer->setInterval(Constants::tick / 2); - connect(m_recvTimer, SIGNAL(timeout()), this, SLOT(tick())); + m_recvTimer->setInterval(Constants::Networking::recv_interval); + connect(m_recvTimer, SIGNAL(timeout()), this, SLOT(readServerUpdates())); } MainWidget::~MainWidget() { doDisconnect(); + deleteGUI(); if (m_host != NULL) { enet_host_destroy(m_host); @@ -38,6 +39,10 @@ MainWidget::~MainWidget() void MainWidget::doConnect(QString srv, unsigned int port) { + /* preload sound - this eliminates some loading gap on slower computers */ + AudioManager::self()->setSource(Sound::Intro); + deleteGUI(); + Color::Color color = connectToServer(srv, port); if (color == Color::none) { @@ -48,7 +53,7 @@ void MainWidget::doConnect(QString srv, unsigned int port) /* create our scene */ m_scene = new SceneHolder(this); m_scene->setColor(color); - m_scene->showWaitingForPlayers(true); + m_scene->showWaitingForPlayers(); createGui(); m_recvTimer->start(); @@ -77,13 +82,26 @@ void MainWidget::deleteLayout(QLayout *layout) delete layout; } +void MainWidget::deleteGUI() +{ + deleteLayout(layout()); + m_playerScoreLayouts.clear(); +} + void MainWidget::doDisconnect() +{ + if (!connected()) + return; + closeENetPeer(); + onDisconnect(); +} + +void MainWidget::onDisconnect() { stopGame(); m_recvTimer->stop(); - closeENetPeer(); - deleteLayout(layout()); - m_playerScoreLayouts.clear(); + m_scene->clear(); + m_scene->showWonLost(didIWinLoose()); emit connected(false); } @@ -157,6 +175,23 @@ void MainWidget::updateScore(const ProtoBuf::MapUpdate& packet) } } +bool MainWidget::didIWinLoose() +{ + QGridLayout *score = m_playerScoreLayouts.at(0); + QLabel *allPointsLbl = dynamic_cast(score->itemAtPosition(1, 1)->widget()); + unsigned long myscore = allPointsLbl->text().toULong(); + + for(unsigned i = 1; i < m_maxplayers; ++i) + { + QGridLayout *score = m_playerScoreLayouts.at(i); + QLabel *allPointsLbl = dynamic_cast(score->itemAtPosition(1, 1)->widget()); + unsigned long other = allPointsLbl->text().toULong(); + if (other > myscore) + return false; + } + return true; +} + Transmission::field_t MainWidget::translateKey(int key) { switch(key) @@ -182,7 +217,7 @@ Transmission::field_t MainWidget::translateKey(int key) } } -void MainWidget::tick() +void MainWidget::readServerUpdates() { ENetEvent event; while (enet_host_service(m_host, &event, 1) > 0) @@ -191,10 +226,10 @@ void MainWidget::tick() { case ENET_EVENT_TYPE_DISCONNECT: m_peer = NULL; - doDisconnect(); + onDisconnect(); break; case ENET_EVENT_TYPE_RECEIVE: - tick(&event); + processServerUpdates(&event); enet_packet_destroy(event.packet); break; default: @@ -203,18 +238,22 @@ void MainWidget::tick() } } -void MainWidget::tick(ENetEvent *event) +void MainWidget::processServerUpdates(ENetEvent *event) { QSharedPointer data = Util::receivePacket(event->packet); - bool worked = m_updatepacket.ParseFromArray(data->data(), data->size()); - Q_ASSERT(worked); - Q_UNUSED(worked); + if (!m_updatepacket.ParseFromArray(data->data(), data->size())) + { + qWarning() << "Invalid update packet from server"; + return; + } /* eating order data set indicates a new round */ if (m_updatepacket.eating_order_size() > 0) { Q_ASSERT(m_scene != NULL); - m_scene->reset(); + + /* stop game */ + stopGame(); /* fetch eating order */ QList order; @@ -222,16 +261,13 @@ void MainWidget::tick(ENetEvent *event) order.append(static_cast(m_updatepacket.eating_order(i) & Transmission::color_mask)); m_scene->setEatingOrder(order); - /* stop game */ - stopGame(); - /* and restart game */ QTimer *timer = new QTimer(this); timer->setSingleShot(true); timer->setInterval(Sound::length[Sound::Intro] + Constants::tick); connect(timer, SIGNAL(timeout()), this, SLOT(startGame())); timer->start(); - AudioManager::self()->audioPlayer()->play(Sound::Intro); + AudioManager::self()->play(Sound::Intro); } Transmission::map_t map = Util::createUninitialisedMap(); @@ -250,10 +286,7 @@ void MainWidget::tick(ENetEvent *event) updateScore(m_updatepacket); if (m_updatepacket.eating_order_size() > 0) - { - m_scene->showWaitingForPlayers(false); m_scene->showEatingText(); - } } void MainWidget::keyPressEvent(QKeyEvent* event) @@ -273,11 +306,13 @@ void MainWidget::keyPressEvent(QKeyEvent* event) void MainWidget::sendKeyUpdate() { + if (!connected()) + return; if (m_currentKey == Transmission::direction_none) return; qDebug() << "[SendKey] key=" << m_currentKey; - ProtoBuf::KeyPressUpdate packet; - packet.set_newkey(m_currentKey); + ProtoBuf::ClientUpdate packet; + packet.set_new_direction(m_currentKey); Util::sendPacket(packet, m_peer, m_host); } @@ -294,7 +329,7 @@ void MainWidget::keyReleaseEvent(QKeyEvent* event) void MainWidget::startGame() { disconnect(AudioManager::self()->audioPlayer(), NULL, this, SLOT(startGame())); - m_scene->showEatingText(false); + m_scene->hideOverlayText(); m_running = true; sendKeyUpdate(); m_ambientPlayer->play(); @@ -304,6 +339,7 @@ void MainWidget::stopGame() { m_running = false; m_ambientPlayer->pause(); + m_scene->reset(); } void MainWidget::setAmbientMuted(bool muted) @@ -348,11 +384,12 @@ Color::Color MainWidget::connectToServer(QString srv, unsigned int port) QSharedPointer data = Util::receivePacket(event.packet); enet_packet_destroy(event.packet); ProtoBuf::Init packet; - worked = packet.ParseFromArray(data->data(), data->size()); - Q_ASSERT(worked); - Q_UNUSED(worked); - m_maxplayers = packet.maxplayers(); - return static_cast(packet.color() & Transmission::color_mask); + if (packet.ParseFromArray(data->data(), data->size())) + { + m_maxplayers = packet.maxplayers(); + return static_cast(packet.color() & Transmission::color_mask); + } + qWarning() << "Invalid initialize packet from server"; } } enet_peer_reset(m_peer); diff --git a/pacman-c++/client/mainwidget.h b/pacman-c++/client/mainwidget.h index 99ff7d7..cfc6cf8 100644 --- a/pacman-c++/client/mainwidget.h +++ b/pacman-c++/client/mainwidget.h @@ -28,6 +28,8 @@ public: public slots: void doConnect(QString srv = "127.0.0.1", unsigned int port = Constants::Networking::port); void doDisconnect(); + void onDisconnect(); + void deleteGUI(); protected: /* handling of current key */ @@ -41,14 +43,15 @@ private slots: void startGame(); void stopGame(); void playerScoreClicked(); - void tick(); - void tick(ENetEvent *event); + void readServerUpdates(); + void processServerUpdates(ENetEvent *event); void sendKeyUpdate(); private: void createGui(); void createMenu(); void updateScore(const ProtoBuf::MapUpdate&); + bool didIWinLoose(); bool isRunning(); Color::Color connectToServer(QString srv = "127.0.0.1", unsigned int port = Constants::Networking::port); void closeENetPeer(); diff --git a/pacman-c++/common.pri b/pacman-c++/common.pri index 38e5c72..eace634 100644 --- a/pacman-c++/common.pri +++ b/pacman-c++/common.pri @@ -16,10 +16,6 @@ contains(TEMPLATE, app) { #win32:LIBS += -lws2_32 -lwinmm } -contains(CONFIG, plugin) { - LIBS += -L.. -lcommon -} - CONFIG(release, debug|release) { DEFINES += QT_NO_DEBUG_OUTPUT } diff --git a/pacman-c++/common/actor.cpp b/pacman-c++/common/actor.cpp index 83a54e3..de8d77e 100644 --- a/pacman-c++/common/actor.cpp +++ b/pacman-c++/common/actor.cpp @@ -296,21 +296,21 @@ void Actor::die() setZValue(zValue() * 10); m_dieing->start(); if (m_local) - AudioManager::self()->audioPlayer()->play(Sound::Die); + AudioManager::self()->play(Sound::Die); } void Actor::eatingFruit() { if (!m_local) return; - AudioManager::self()->audioPlayer()->play(Sound::EatingFruit); + AudioManager::self()->play(Sound::EatingFruit); } void Actor::eatingPacman() { if (!m_local) return; - AudioManager::self()->audioPlayer()->play(Sound::EatingGhost); + AudioManager::self()->play(Sound::EatingGhost); } void Actor::startEating() diff --git a/pacman-c++/common/audio.cpp b/pacman-c++/common/audio.cpp index d29303d..eddbace 100644 --- a/pacman-c++/common/audio.cpp +++ b/pacman-c++/common/audio.cpp @@ -23,7 +23,7 @@ AudioManager::AudioManager() } preload(); - if (!tryLoadPhononPlugin()) + if (!tryLoadAudioPlugin("*phononplayer*")) { qWarning() << "Unable to load audio plugin. Audio disabled.."; m_players.append(new NoopAudioPlayer(this)); @@ -31,6 +31,7 @@ AudioManager::AudioManager() } AudioPlayer *firstplayer = m_factory->create(this); + firstplayer->setWorking(m_working); firstplayer->test(m_sounds[Sound::EatingFruit], Sound::length[Sound::EatingFruit] * 2); m_working = firstplayer->isWorking(); m_players.append(firstplayer); @@ -118,6 +119,33 @@ void AudioManager::unregisterAudioPlayer(AudioPlayer *player) m_players.removeAll(player); } + +void AudioManager::unregisterAudioPlayer_helper(QObject *player) +{ + unregisterAudioPlayer(static_cast(player)); +} + +void AudioManager::play(Sound::Type sound, AudioPlayer *player) +{ + if (player == NULL) + player = audioPlayer(); + player->play(this->sound(sound), length(sound)); +} + +void AudioManager::setSource(Sound::Type sound, AudioPlayer *player) +{ + if (player == NULL) + player = audioPlayer(); + player->setSource(this->sound(sound), length(sound)); +} + +void AudioManager::enqueue(Sound::Type sound, AudioPlayer *player) +{ + if (player == NULL) + player = audioPlayer(); + player->enqueue(this->sound(sound), length(sound)); +} + QFile *AudioManager::sound(Sound::Type sound) { if (!isWorking()) @@ -125,9 +153,9 @@ QFile *AudioManager::sound(Sound::Type sound) return m_sounds.at(sound); } -void AudioManager::unregisterAudioPlayer_helper(QObject *player) +unsigned int AudioManager::length(Sound::Type sound) { - unregisterAudioPlayer(static_cast(player)); + return Sound::length[sound]; } void AudioManager::preload() @@ -137,13 +165,14 @@ void AudioManager::preload() Q_ASSERT(sounds.count() > 0); for(unsigned i = 1; i <= sounds.count(); ++i) m_sounds.append(new QFile(QString(":/sound/sound%1").arg(i), this)); + Q_ASSERT(m_sounds.count() != (sizeof(Sound::length) / sizeof(unsigned int))); } -bool AudioManager::tryLoadPhononPlugin() +bool AudioManager::tryLoadAudioPlugin(const QString &libraryname) { QDir dir = qApp->applicationDirPath(); QStringList filters; - filters << "*phononplayer*"; + filters << libraryname; foreach (QString file, dir.entryList(filters, QDir::Files)) { file = dir.absoluteFilePath(file); @@ -163,25 +192,19 @@ bool AudioManager::tryLoadPhononPlugin() return false; } -AudioPlayer *AudioManager::createAudioPlayer() +AudioPlayer *AudioManager::createAudioPlayer(QObject *parent) { if (m_factory == NULL) return NULL; - AudioPlayer *player = m_factory->create(this); + AudioPlayer *player = m_factory->create(parent != NULL ? parent : this); + player->setWorking(m_working); registerAudioPlayer(player); return player; } /* --------------------------------------------------------------- */ -AudioPlayer *NoopAudioPlayerFactory::create(QObject *parent) -{ - return new FakeAudioPlayer(parent); -} - -/* --------------------------------------------------------------- */ - NoopAudioPlayer::NoopAudioPlayer(QObject *parent) : AudioPlayer(parent), m_working(false), m_muted(false), m_playing(false), m_paused(false) {} @@ -209,19 +232,6 @@ void NoopAudioPlayer::play() m_playing = false; } -void NoopAudioPlayer::play(Sound::Type /* sound */) -{ - play(); -} - -bool NoopAudioPlayer::isPlaying() -{ - return m_playing; -} - -void NoopAudioPlayer::enqueue(Sound::Type /* sound */) -{} - void NoopAudioPlayer::pause() { m_paused = true; @@ -258,7 +268,32 @@ void NoopAudioPlayer::prefinishMarkReached_ex(qint32 mark) emit prefinishMarkReached(mark); } -void NoopAudioPlayer::test(QFile * /* testsound */, qint32 /* length */) +void NoopAudioPlayer::seek(qint64 /* time */) +{} + +void NoopAudioPlayer::setWorking(bool working) +{ + m_working = working; +} + +void NoopAudioPlayer::test(QFile * /* sound */, unsigned int /* length */) +{} + +void NoopAudioPlayer::play(QFile *sound, unsigned int length) +{ + setSource(sound, length); + play(); +} + +void NoopAudioPlayer::setSource(QFile * /* sound */, unsigned int /* length */) +{} + +bool NoopAudioPlayer::isPlaying() +{ + return m_playing; +} + +void NoopAudioPlayer::enqueue(QFile * /* sound */, unsigned int /* length */) {} /* --------------------------------------------------------------- */ @@ -270,13 +305,13 @@ FakeAudioPlayer::FakeAudioPlayer(QObject *parent) connect(&m_timer, SIGNAL(timeout()), this, SLOT(finished_ex())); } -void FakeAudioPlayer::play(Sound::Type sound) +void FakeAudioPlayer::play(QFile * /* sound */, unsigned int length) { m_playing = true; m_paused = false; m_timer.setSingleShot(true); - unsigned int interval = Sound::length[sound]; + unsigned int interval = length; /* add a small delay server side only */ if (Constants::server) interval += Constants::tick; @@ -299,17 +334,15 @@ GaplessAudioPlayer::GaplessAudioPlayer(Sound::Type sound, qint32 mark, QObject * if (!m_working) return; - m_player1 = AudioManager::self()->createAudioPlayer(); - m_player2 = AudioManager::self()->createAudioPlayer(); + m_player1 = AudioManager::self()->createAudioPlayer(this); + m_player2 = AudioManager::self()->createAudioPlayer(this); + /* this doesn't work reliable on all platforms (e.g. windows) */ m_player2->setPrefinishMark(mark); m_player1->setPrefinishMark(mark); connect(m_player1, SIGNAL(prefinishMarkReached(qint32)), this, SLOT(startPlayer2())); connect(m_player2, SIGNAL(prefinishMarkReached(qint32)), this, SLOT(startPlayer1())); - - AudioManager::self()->registerAudioPlayer(m_player1); - AudioManager::self()->registerAudioPlayer(m_player2); } bool GaplessAudioPlayer::isWorking() const @@ -350,10 +383,12 @@ void GaplessAudioPlayer::pause() void GaplessAudioPlayer::startPlayer1() { - m_player1->play(m_sound); + AudioManager::self()->play(m_sound, m_player1); + m_player2->pause(); } void GaplessAudioPlayer::startPlayer2() { - m_player2->play(m_sound); + AudioManager::self()->play(m_sound, m_player2); + m_player1->pause(); } diff --git a/pacman-c++/common/audio.h b/pacman-c++/common/audio.h index bc7d66e..45af34b 100644 --- a/pacman-c++/common/audio.h +++ b/pacman-c++/common/audio.h @@ -1,6 +1,7 @@ #ifndef AUDIO_H #define AUDIO_H +#include "audiointerface.h" #include #include #include @@ -19,52 +20,12 @@ namespace Sound }; const unsigned int length[] = { - 4310, 2090, 570, 570, 1720, + 4310, 2090, 570, 570, 1720, 1990 }; }; /* --------------------------------------------------------------- */ -class AudioPlayer - : public QObject -{ - Q_OBJECT - friend class AudioManager; - -public: - AudioPlayer(QObject *parent = 0) - : QObject(parent) - {} - virtual ~AudioPlayer() - {} - virtual bool isWorking() const = 0; - virtual void setMuted(bool mute = true) = 0; - virtual bool isMuted() const = 0; - virtual void play() = 0; - virtual void play(Sound::Type sound) = 0; - virtual bool isPlaying() = 0; - virtual void enqueue(Sound::Type sound) = 0; - virtual void pause() = 0; - virtual bool isPaused() = 0; - virtual void stop() = 0; - virtual bool isStopped() = 0; - virtual void clear() = 0; - virtual void clearQueue() = 0; - virtual void setPrefinishMark(qint32 msecToEnd) = 0; - -protected slots: - virtual void prefinishMarkReached_ex(qint32 mark) = 0; - -signals: - void finished(); - void prefinishMarkReached(qint32 mark); - -protected: - virtual void test(QFile *testsound, qint32 length) = 0; -}; - -/* --------------------------------------------------------------- */ - class NoopAudioPlayer : public AudioPlayer { @@ -72,14 +33,11 @@ class NoopAudioPlayer friend class AudioManager; public: - NoopAudioPlayer(QObject *parent = 0); virtual bool isWorking() const; virtual void setMuted(bool mute = true); virtual bool isMuted() const; virtual void play(); - virtual void play(Sound::Type sound); virtual bool isPlaying(); - virtual void enqueue(Sound::Type sound); virtual void pause(); virtual bool isPaused(); virtual void stop(); @@ -87,13 +45,19 @@ public: virtual void clear(); virtual void clearQueue(); virtual void setPrefinishMark(qint32 msecToEnd); + virtual void seek(qint64 time); + +protected: + NoopAudioPlayer(QObject *parent = 0); + virtual void setWorking(bool working = true); + virtual void test(QFile *sound, unsigned int length); + virtual void play(QFile *sound, unsigned int length); + virtual void setSource(QFile *sound, unsigned int length); + virtual void enqueue(QFile *sound, unsigned int length); protected slots: virtual void prefinishMarkReached_ex(qint32 mark); -protected: - virtual void test(QFile *testsound, qint32 length); - protected: bool m_working; bool m_muted; @@ -109,9 +73,9 @@ class FakeAudioPlayer Q_OBJECT friend class AudioManager; -public: +protected: FakeAudioPlayer(QObject *parent = 0); - virtual void play(Sound::Type sound); + virtual void play(QFile *sound, unsigned int length); protected slots: void finished_ex(); @@ -148,27 +112,6 @@ protected: /* --------------------------------------------------------------- */ -class AudioPlayerFactory -{ -public: - virtual ~AudioPlayerFactory() - {} - virtual AudioPlayer *create(QObject *parent = 0) = 0; -}; - -Q_DECLARE_INTERFACE(AudioPlayerFactory, "at.ac.tuwien.foop.pacman.AudioPlayerFactory/1.0"); - -/* --------------------------------------------------------------- */ - -class NoopAudioPlayerFactory - : public AudioPlayerFactory -{ -public: - virtual AudioPlayer *create(QObject *parent = 0); -}; - -/* --------------------------------------------------------------- */ - class AudioManager : public QObject { @@ -189,8 +132,9 @@ public: AudioPlayer *audioPlayer(); void registerAudioPlayer(AudioPlayer *player); void unregisterAudioPlayer(AudioPlayer *player); - - QFile *sound(Sound::Type sound); + void play(Sound::Type sound, AudioPlayer *player = NULL); + void setSource(Sound::Type sound, AudioPlayer *player = NULL); + void enqueue(Sound::Type sound, AudioPlayer *player = NULL); signals: void mutedChanged(bool muted); @@ -200,8 +144,10 @@ private slots: protected: void preload(); - bool tryLoadPhononPlugin(); - AudioPlayer *createAudioPlayer(); + bool tryLoadAudioPlugin(const QString &libraryname); + AudioPlayer *createAudioPlayer(QObject *parent = 0); + QFile *sound(Sound::Type sound); + unsigned int length(Sound::Type sound); private: bool m_muted; @@ -212,4 +158,4 @@ private: AudioPlayerFactory *m_factory; }; -#endif // AUDIOPLAYER_H +#endif // AUDIO_H diff --git a/pacman-c++/common/audiointerface.h b/pacman-c++/common/audiointerface.h new file mode 100644 index 0000000..66679b6 --- /dev/null +++ b/pacman-c++/common/audiointerface.h @@ -0,0 +1,60 @@ +#ifndef AUDIOINTERFACE_H +#define AUDIOINTERFACE_H + +#include +#include + +class AudioPlayer + : public QObject +{ + Q_OBJECT + friend class AudioManager; + +public: + virtual ~AudioPlayer() + {} + virtual bool isWorking() const = 0; + virtual void setMuted(bool mute = true) = 0; + virtual bool isMuted() const = 0; + virtual void play() = 0; + virtual bool isPlaying() = 0; + virtual void pause() = 0; + virtual bool isPaused() = 0; + virtual void stop() = 0; + virtual bool isStopped() = 0; + virtual void clear() = 0; + virtual void clearQueue() = 0; + virtual void setPrefinishMark(qint32 msecToEnd) = 0; + virtual void seek(qint64 time) = 0; + +signals: + void finished(); + void prefinishMarkReached(qint32 mark); + +protected: + AudioPlayer(QObject *parent = 0) + : QObject(parent) + {} + virtual void setWorking(bool working = true) = 0; + virtual void test(QFile *sound, unsigned int length) = 0; + virtual void play(QFile *sound, unsigned int length) = 0; + virtual void setSource(QFile *sound, unsigned int length) = 0; + virtual void enqueue(QFile *sound, unsigned int length) = 0; + +protected slots: + virtual void prefinishMarkReached_ex(qint32 mark) = 0; +}; + +/* --------------------------------------------------------------- */ + +class AudioPlayerFactory +{ +public: + virtual ~AudioPlayerFactory() + {} + virtual AudioPlayer *create(QObject *parent = 0) = 0; +}; + +Q_DECLARE_INTERFACE(AudioPlayerFactory, "at.ac.tuwien.foop.pacman.AudioPlayerFactory/1.0"); + +#endif // AUDIOINTERFACE_H diff --git a/pacman-c++/common/common.pro b/pacman-c++/common/common.pro index 1114e17..39481c0 100644 --- a/pacman-c++/common/common.pro +++ b/pacman-c++/common/common.pro @@ -24,7 +24,8 @@ HEADERS += pixmapitem.h \ audio.h \ sceneholder.h \ util.h \ - gameentity.h + gameentity.h \ + audiointerface.h OTHER_FILES += style.qss \ pacman.rc diff --git a/pacman-c++/common/constants.h b/pacman-c++/common/constants.h index d40c39e..7f32422 100644 --- a/pacman-c++/common/constants.h +++ b/pacman-c++/common/constants.h @@ -22,6 +22,7 @@ namespace Constants { const unsigned int port = 7321; const unsigned int connection_timeout = 3000; const unsigned int packet_timeout = 3000; + const unsigned int recv_interval = Constants::tick / 2; } namespace Game diff --git a/pacman-c++/common/sceneholder.cpp b/pacman-c++/common/sceneholder.cpp index bd9b01b..d429445 100644 --- a/pacman-c++/common/sceneholder.cpp +++ b/pacman-c++/common/sceneholder.cpp @@ -23,7 +23,7 @@ SceneHolder::SceneHolder(QObject *parent) void SceneHolder::reset() { processDelayedItems(); - showEatingText(false); + hideOverlayText(); /* remove actors from scene so they don't get deleted during clear */ foreach(Actor *actor, m_actors) @@ -272,15 +272,22 @@ QList &SceneHolder::eatingOrder() return m_eatingorder; } -void SceneHolder::showEatingText(bool show) +void SceneHolder::hideOverlayText() { - if (!show) - { - if (m_overlayText->scene() == this) - removeItem(m_overlayText); - return; - } + if (m_overlayText->scene() == this) + removeItem(m_overlayText); +} + +void SceneHolder::centerOverlayText(unsigned int lines) +{ + QFontMetrics metrics(m_overlayText->font()); + m_overlayText->setPos((width() - m_overlayText->textWidth()) / 2, (height() - metrics.height() * lines) / 2); + m_overlayText->setZValue(100); +} +void SceneHolder::showEatingText() +{ + hideOverlayText(); m_overlayText->setDefaultTextColor(Qt::black); QString text = QString( "
" @@ -307,23 +314,14 @@ void SceneHolder::showEatingText(bool show) 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); + centerOverlayText(lines); addItem(m_overlayText); } -void SceneHolder::showWaitingForPlayers(bool show) +void SceneHolder::showWaitingForPlayers() { - if (!show) - { - if (m_overlayText->scene() == this) - removeItem(m_overlayText); - return; - } - + hideOverlayText(); m_overlayText->setDefaultTextColor(Qt::black); QString text = QString( "
" @@ -335,10 +333,26 @@ void SceneHolder::showWaitingForPlayers(bool show) m_overlayText->setHtml(text); m_overlayText->setTextWidth(150); m_overlayText->setOpacity(0.9); + centerOverlayText(lines); - 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::showWonLost(bool won) +{ + hideOverlayText(); + m_overlayText->setDefaultTextColor(Qt::black); + QString text = QString( + "
" + "
" + "You %1!
" + "
" + ).arg((won) ? "won" : "lost"); + unsigned int lines = 3; + m_overlayText->setHtml(text); + m_overlayText->setTextWidth(150); + m_overlayText->setOpacity(0.9); + centerOverlayText(lines); addItem(m_overlayText); } diff --git a/pacman-c++/common/sceneholder.h b/pacman-c++/common/sceneholder.h index 0872837..801b98b 100644 --- a/pacman-c++/common/sceneholder.h +++ b/pacman-c++/common/sceneholder.h @@ -24,8 +24,12 @@ public: Color::Color color(); void setEatingOrder(QList &order); QList &eatingOrder(); - void showEatingText(bool show = true); - void showWaitingForPlayers(bool show = true); + + void hideOverlayText(); + void centerOverlayText(unsigned int lines); + void showEatingText(); + void showWaitingForPlayers(); + void showWonLost(bool won); signals: void allPointsRemoved(); diff --git a/pacman-c++/phononplayer/phononplayer.cpp b/pacman-c++/phononplayer/phononplayer.cpp index 1f537d6..3d7b446 100644 --- a/pacman-c++/phononplayer/phononplayer.cpp +++ b/pacman-c++/phononplayer/phononplayer.cpp @@ -1,4 +1,5 @@ #include "phononplayer.h" +#include "audio.h" #include #include @@ -12,9 +13,8 @@ Q_EXPORT_PLUGIN2(phononplayer, PhononPlayerFactory) /* --------------------------------------------------------------- */ PhononPlayer::PhononPlayer(QObject *parent) - : AudioPlayer(parent) + : AudioPlayer(parent), m_working(false) { - m_working = AudioManager::isWorking(); m_player = new Phonon::MediaObject(this); m_output = new Phonon::AudioOutput(Phonon::MusicCategory, this); Phonon::createPath(m_player, m_output); @@ -39,25 +39,36 @@ bool PhononPlayer::isMuted() const void PhononPlayer::play() { + if (!m_working) + return; m_player->play(); } -void PhononPlayer::play(Sound::Type sound) +void PhononPlayer::play(QFile *sound, unsigned int length) { if (!m_working) return; - m_player->setCurrentSource(Phonon::MediaSource(AudioManager::self()->sound(sound))); + setSource(sound, length); play(); } +void PhononPlayer::setSource(QFile *sound, unsigned int /* length */) +{ + if (!m_working) + return; + m_player->setCurrentSource(Phonon::MediaSource(sound)); +} + bool PhononPlayer::isPlaying() { return m_player->state() == Phonon::PlayingState; } -void PhononPlayer::enqueue(Sound::Type sound) +void PhononPlayer::enqueue(QFile *sound, unsigned int /* length */) { - m_player->enqueue(Phonon::MediaSource(AudioManager::self()->sound(sound))); + if (!m_working) + return; + m_player->enqueue(Phonon::MediaSource(sound)); } void PhononPlayer::pause() @@ -96,12 +107,22 @@ void PhononPlayer::setPrefinishMark(qint32 msecToEnd) m_player->setPrefinishMark(msecToEnd); } +void PhononPlayer::seek(qint64 time) +{ + m_player->seek(time); +} + +void PhononPlayer::setWorking(bool working) +{ + m_working = working; +} + /* this is a simple hack to check if phonon can actually play sounds.. */ -void PhononPlayer::test(QFile *testsound, qint32 length) +void PhononPlayer::test(QFile *sound, unsigned int length) { m_player->stop(); m_output->setVolume(0); - m_player->setCurrentSource(Phonon::MediaSource(testsound)); + m_player->setCurrentSource(Phonon::MediaSource(sound)); connect(m_player, SIGNAL(stateChanged(Phonon::State, Phonon::State)), this, SLOT(stateChanged_ex(Phonon::State, Phonon::State))); m_player->play(); diff --git a/pacman-c++/phononplayer/phononplayer.h b/pacman-c++/phononplayer/phononplayer.h index ca56726..8b9ab06 100644 --- a/pacman-c++/phononplayer/phononplayer.h +++ b/pacman-c++/phononplayer/phononplayer.h @@ -1,7 +1,7 @@ #ifndef PHONONPLAYER_H #define PHONONPLAYER_H -#include "audio.h" +#include "audiointerface.h" #include #include #include @@ -25,6 +25,7 @@ class PhononPlayer { Q_OBJECT friend class AudioManager; + friend class PhononPlayerFactory; private: class Sleeper @@ -37,14 +38,11 @@ private: }; public: - PhononPlayer(QObject *parent = 0); virtual bool isWorking() const; virtual void setMuted(bool mute = true); virtual bool isMuted() const; virtual void play(); - virtual void play(Sound::Type sound); virtual bool isPlaying(); - virtual void enqueue(Sound::Type sound); virtual void pause(); virtual bool isPaused(); virtual void stop(); @@ -52,9 +50,15 @@ public: virtual void clear(); virtual void clearQueue(); virtual void setPrefinishMark(qint32 msecToEnd); + virtual void seek(qint64 time); protected: - void test(QFile *testsound, qint32 length); + PhononPlayer(QObject *parent = 0); + virtual void setWorking(bool working = true); + void test(QFile *sound, unsigned int length); + virtual void play(QFile *sound, unsigned int length); + virtual void setSource(QFile *sound, unsigned int length); + virtual void enqueue(QFile *sound, unsigned int length); protected slots: virtual void prefinishMarkReached_ex(qint32 mark); diff --git a/pacman-c++/phononplayer/phononplayer.pro b/pacman-c++/phononplayer/phononplayer.pro index 9482454..a11626c 100644 --- a/pacman-c++/phononplayer/phononplayer.pro +++ b/pacman-c++/phononplayer/phononplayer.pro @@ -8,4 +8,5 @@ QT += phonon include(../common.pri) SOURCES += phononplayer.cpp -HEADERS += phononplayer.h +HEADERS += phononplayer.h \ + ../common/audiointerface.h diff --git a/pacman-c++/proto/pacman.proto b/pacman-c++/proto/pacman.proto index 8e088e8..cc4aabc 100644 --- a/pacman-c++/proto/pacman.proto +++ b/pacman-c++/proto/pacman.proto @@ -1,7 +1,7 @@ package ProtoBuf; -message KeyPressUpdate { - required uint32 newKey = 1; +message ClientUpdate { + required uint32 new_direction = 1; } message Init { diff --git a/pacman-c++/server/server.cpp b/pacman-c++/server/server.cpp index 877c4a6..316b719 100644 --- a/pacman-c++/server/server.cpp +++ b/pacman-c++/server/server.cpp @@ -84,8 +84,8 @@ void Server::tick() return; } - /* fetch key updates */ - keyPressUpdate(); + /* fetch client updates */ + readClientUpdates(); /* let the bots move */ foreach (Color::Color color, m_bots) @@ -402,7 +402,7 @@ bool Server::waitForClientConnections() } char buf[1024]; - enet_address_get_host_ip(&m_host->address, buf, 1024); + enet_address_get_host_ip(&m_host->address, buf, sizeof(buf)); std::cout << "[Server] Listening on: " << qPrintable(QString("%1:%2").arg(buf).arg(m_host->address.port)) << std::endl; @@ -431,14 +431,18 @@ bool Server::waitForClientConnections() m_clientConnections[event.peer] = color; packet.set_color(color); Util::sendPacket(packet, event.peer, m_host); - std::cout << "[Connect] New Player: color=" << qPrintable(Util::colorToString(color)) << std::endl; + + char buf[1024]; + enet_address_get_host_ip(&event.peer->address, buf, sizeof(buf)); + std::cout << "[Connect] New Player: color=" << qPrintable(Util::colorToString(color)) + << ", address=" << buf << ':' << event.peer->address.port << std::endl; } break; case ENET_EVENT_TYPE_RECEIVE: - keyPressUpdate(&event); + processClientUpdate(&event); break; case ENET_EVENT_TYPE_DISCONNECT: - keyPressUpdate(&event); + processClientUpdate(&event); break; default: break; @@ -626,28 +630,29 @@ void Server::botCalculate(Actor *actor) m_actorMovements[actor->color()] = list.at(rand); } -void Server::keyPressUpdate() +void Server::readClientUpdates() { - ProtoBuf::KeyPressUpdate packet; ENetEvent event; while (enet_host_service(m_host, &event, 1) > 0) - keyPressUpdate(&event); + processClientUpdate(&event); } -void Server::keyPressUpdate(ENetEvent *event) +void Server::processClientUpdate(ENetEvent *event) { - ProtoBuf::KeyPressUpdate packet; switch(event->type) { case ENET_EVENT_TYPE_RECEIVE: { QSharedPointer data = Util::receivePacket(event->packet); enet_packet_destroy(event->packet); - bool worked = packet.ParseFromArray(data->data(), data->size()); - Q_ASSERT(worked); - Q_UNUSED(worked); - Transmission::field_t direction = packet.newkey(); + ProtoBuf::ClientUpdate packet; Color::Color color = m_clientConnections[event->peer]; + if (!packet.ParseFromArray(data->data(), data->size())) + { + qWarning() << "Invalid packet from client color=" << color; + return; + } + Transmission::field_t direction = packet.new_direction(); qDebug() << "[KeyPress] actor=" << color << "direction=" << direction; m_actorMovements[color] = Util::transmissionMovementToActor(direction); } @@ -760,7 +765,7 @@ void Server::initRoundMap() disconnect(AudioManager::self()->audioPlayer(), NULL, this, NULL); connect(AudioManager::self()->audioPlayer(), SIGNAL(finished()), this, SLOT(startGame())); - AudioManager::self()->audioPlayer()->play(Sound::Intro); + AudioManager::self()->play(Sound::Intro); m_tickTimer->start(); } @@ -782,7 +787,7 @@ void Server::stopGame(bool delay) { disconnect(AudioManager::self()->audioPlayer(), NULL, this, NULL); connect(AudioManager::self()->audioPlayer(), SIGNAL(finished()), this, SLOT(stopGame())); - AudioManager::self()->audioPlayer()->play(Sound::Die); + AudioManager::self()->play(Sound::Die); return; } diff --git a/pacman-c++/server/server.h b/pacman-c++/server/server.h index 857f23d..26c1af2 100644 --- a/pacman-c++/server/server.h +++ b/pacman-c++/server/server.h @@ -11,8 +11,6 @@ extern "C" { #include "enet/enet.h" } -class QTcpSocket; - class Server : public SceneHolder { @@ -27,8 +25,8 @@ protected slots: void tick(); /* receive updates of client */ - void keyPressUpdate(); - void keyPressUpdate(ENetEvent *event); + void readClientUpdates(); + void processClientUpdate(ENetEvent *event); protected: /* block until we have connections from all clients */ -- cgit v1.2.3