summaryrefslogtreecommitdiffstats
path: root/pacman-c++
diff options
context:
space:
mode:
authormanuel <manuel@mausz.at>2011-04-25 14:39:00 +0200
committermanuel <manuel@mausz.at>2011-04-25 14:39:00 +0200
commit41a31420cf091aeb4e986503387855d41e550106 (patch)
treeffbe0be5f9630a0bab2deb0b5df37c174bf40db1 /pacman-c++
parentbbd2a69a962d15f74a4afcb7b66462eac9fa5008 (diff)
downloadfoop-41a31420cf091aeb4e986503387855d41e550106.tar.gz
foop-41a31420cf091aeb4e986503387855d41e550106.tar.bz2
foop-41a31420cf091aeb4e986503387855d41e550106.zip
- add intro sound on every round
- add dieing sound - add dieing animation - add die on moving onto colorized block
Diffstat (limited to 'pacman-c++')
-rw-r--r--pacman-c++/actor.cpp49
-rw-r--r--pacman-c++/actor.h7
-rw-r--r--pacman-c++/audio.cpp54
-rw-r--r--pacman-c++/audio.h9
-rw-r--r--pacman-c++/block.cpp19
-rw-r--r--pacman-c++/block.h3
-rw-r--r--pacman-c++/bonuspoint.cpp5
-rw-r--r--pacman-c++/bonuspoint.h2
-rw-r--r--pacman-c++/constants.h9
-rw-r--r--pacman-c++/gameentity.cpp4
-rw-r--r--pacman-c++/gameentity.h20
-rw-r--r--pacman-c++/mainwidget.cpp29
-rw-r--r--pacman-c++/mainwidget.h1
-rw-r--r--pacman-c++/pics/actor1.pngbin796 -> 1231 bytes
-rw-r--r--pacman-c++/pics/actor2.pngbin805 -> 1257 bytes
-rw-r--r--pacman-c++/pics/actor3.pngbin793 -> 1226 bytes
-rw-r--r--pacman-c++/pics/actor4.pngbin804 -> 1536 bytes
-rw-r--r--pacman-c++/point.cpp5
-rw-r--r--pacman-c++/point.h2
-rw-r--r--pacman-c++/sceneholder.cpp76
-rw-r--r--pacman-c++/sceneholder.h4
-rw-r--r--pacman-c++/server.cpp143
-rw-r--r--pacman-c++/server.h9
23 files changed, 286 insertions, 164 deletions
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)
57 m_eating.append(setupEatingAnimation(Actor::Up)); 57 m_eating.append(setupEatingAnimation(Actor::Up));
58 m_eating.append(setupEatingAnimation(Actor::Down)); 58 m_eating.append(setupEatingAnimation(Actor::Down));
59 59
60 /* dieing animation */
61 m_dieing = new QSequentialAnimationGroup(this);
62 for (int i = 0; i < 11; i++)
63 {
64 PixmapItem *img = new PixmapItem(m_pix, this);
65 m_images.append(img);
66 int x = i * Constants::sprite_offset + Constants::sprite_margin;
67 int y = 5 * Constants::sprite_offset + Constants::sprite_margin;
68 img->setSprite(x, y, Constants::field_size.width, Constants::field_size.height);
69 img->setZValue(zValue());
70 img->setVisible(false);
71
72 QPropertyAnimation *fadein = new QPropertyAnimation(img, "visible", m_dieing);
73 fadein->setDuration(0);
74 fadein->setEndValue(true);
75
76 m_dieing->addPause(130);
77
78 QPropertyAnimation *fadeout = new QPropertyAnimation(img, "visible", m_dieing);
79 fadeout->setDuration(0);
80 fadeout->setEndValue(false);
81 }
82
60 /* setup waka sound */ 83 /* setup waka sound */
61 if (local) 84 if (local)
62 m_wakaPlayer = new GaplessAudioPlayer(Sound::WakaWaka, 100, this); 85 m_wakaPlayer = new GaplessAudioPlayer(Sound::WakaWaka, 100, this);
@@ -112,11 +135,21 @@ bool Actor::isLocal()
112 return m_local; 135 return m_local;
113} 136}
114 137
115void Actor::resetDirection() 138void Actor::resetAnimation()
116{ 139{
140 if (Constants::server)
141 return;
142
143 stopEating();
144 m_moving->stop();
145 m_dieing->stop();
117 /* hide all pictures */ 146 /* hide all pictures */
118 for (int i = 0; i < m_images.size(); ++i) 147 for (int i = 0; i < m_images.size(); ++i)
119 m_images.at(i)->setVisible(false); 148 m_images.at(i)->setVisible(false);
149
150 if (m_eating[m_direction] != NULL)
151 m_eating[m_direction]->stop();
152
120 m_direction = Actor::None; 153 m_direction = Actor::None;
121 m_images[m_direction]->setVisible(true); 154 m_images[m_direction]->setVisible(true);
122} 155}
@@ -213,9 +246,14 @@ bool Actor::canEat(Actor *other, const QList<Color::Color> &order)
213 246
214void Actor::die() 247void Actor::die()
215{ 248{
216 if (!m_local) 249 if (Constants::server)
217 return; 250 return;
218 AudioManager::self()->play(Sound::Die); 251
252 resetAnimation();
253 m_images[m_direction]->setVisible(false);
254 m_dieing->start();
255 if (m_local)
256 AudioManager::self()->play(Sound::Die);
219} 257}
220 258
221void Actor::eatingFruit() 259void Actor::eatingFruit()
@@ -261,9 +299,10 @@ void Actor::addRoundPoints(unsigned int amount)
261 m_roundPoints += amount; 299 m_roundPoints += amount;
262} 300}
263 301
264void Actor::finishRound() 302void Actor::finishRound(bool died)
265{ 303{
266 m_gamePoints += m_roundPoints; 304 if (!died)
305 m_gamePoints += m_roundPoints;
267 m_roundPoints = 0; 306 m_roundPoints = 0;
268} 307}
269 308
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
16public: 16public:
17 enum Movement 17 enum Movement
18 { 18 {
19 None = 0, 19 None = 0,
20 Left, 20 Left,
21 Right, 21 Right,
22 Up, 22 Up,
@@ -34,7 +34,7 @@ public:
34 34
35 PixmapItem &icon(); 35 PixmapItem &icon();
36 Movement direction(); 36 Movement direction();
37 void resetDirection(); 37 void resetAnimation();
38 bool isLocal(); 38 bool isLocal();
39 void move(Movement direction); 39 void move(Movement direction);
40 bool isMoving(); 40 bool isMoving();
@@ -48,7 +48,7 @@ public:
48 unsigned int getRoundPoints(); 48 unsigned int getRoundPoints();
49 unsigned int getGamePoints(); 49 unsigned int getGamePoints();
50 void addRoundPoints(unsigned int amount); 50 void addRoundPoints(unsigned int amount);
51 void finishRound(); 51 void finishRound(bool died = false);
52 52
53 static QPoint movementToPoint(const Actor::Movement direction); 53 static QPoint movementToPoint(const Actor::Movement direction);
54 54
@@ -69,6 +69,7 @@ private:
69 QList<PixmapItem *> m_images; 69 QList<PixmapItem *> m_images;
70 QList<QSequentialAnimationGroup *> m_eating; 70 QList<QSequentialAnimationGroup *> m_eating;
71 QParallelAnimationGroup *m_moving; 71 QParallelAnimationGroup *m_moving;
72 QSequentialAnimationGroup *m_dieing;
72}; 73};
73 74
74#endif // ACTOR_H 75#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()
15 : m_muted(true) 15 : m_muted(true)
16{ 16{
17 if (Constants::server) 17 if (Constants::server)
18 {
18 qDebug() << "Server has no sound"; 19 qDebug() << "Server has no sound";
20 m_players.append(new AudioPlayer(this));
21 }
19 else 22 else
20 { 23 {
21 preload(); 24 preload();
22
23 AudioPlayer *firstplayer = new AudioPlayer(this); 25 AudioPlayer *firstplayer = new AudioPlayer(this);
24 firstplayer->test(m_sounds[Sound::WakaWaka]); 26 firstplayer->test(m_sounds[Sound::WakaWaka]);
25 m_working = firstplayer->m_working; 27 m_working = firstplayer->m_working;
26 m_players.append(firstplayer); 28 m_players.append(firstplayer);
27
28 m_muted = false;
29 } 29 }
30 m_muted = false;
30} 31}
31 32
32AudioManager *AudioManager::self() 33AudioManager *AudioManager::self()
@@ -97,15 +98,9 @@ AudioPlayer *AudioManager::audioPlayer()
97 return m_players.at(0); 98 return m_players.at(0);
98} 99}
99 100
100void AudioManager::play(Sound::Type sound) 101void AudioManager::play(Sound::Type sound, bool wait)
101{ 102{
102 if (!isWorking()) 103 audioPlayer()->play(sound, wait);
103 {
104 emit audioPlayer()->finished();
105 return;
106 }
107
108 audioPlayer()->play(sound);
109} 104}
110 105
111void AudioManager::enqueue(Sound::Type sound) 106void AudioManager::enqueue(Sound::Type sound)
@@ -151,11 +146,14 @@ QFile *AudioManager::sound(Sound::Type sound)
151/* --------------------------------------------------------------- */ 146/* --------------------------------------------------------------- */
152 147
153AudioPlayer::AudioPlayer(QObject *parent) 148AudioPlayer::AudioPlayer(QObject *parent)
154 : Phonon::MediaObject(parent) 149 : Phonon::MediaObject(parent), m_working(false)
155{ 150{
156 m_working = AudioManager::m_working; 151 if (!Constants::server)
157 m_output = new Phonon::AudioOutput(Phonon::MusicCategory, this); 152 {
158 Phonon::createPath(this, m_output); 153 m_working = AudioManager::m_working;
154 m_output = new Phonon::AudioOutput(Phonon::MusicCategory, this);
155 Phonon::createPath(this, m_output);
156 }
159} 157}
160 158
161bool AudioPlayer::isWorking() const 159bool AudioPlayer::isWorking() const
@@ -200,10 +198,25 @@ void AudioPlayer::play()
200 Phonon::MediaObject::play(); 198 Phonon::MediaObject::play();
201} 199}
202 200
203void AudioPlayer::play(Sound::Type sound) 201void AudioPlayer::play(Sound::Type sound, bool wait)
204{ 202{
205 setCurrentSource(Phonon::MediaSource(AudioManager::self()->sound(sound))); 203 if (m_working)
206 play(); 204 {
205 setCurrentSource(Phonon::MediaSource(AudioManager::self()->sound(sound)));
206 play();
207 }
208 else if (wait)
209 {
210 QTimer *timer = new QTimer(this);
211 timer->setSingleShot(true);
212 unsigned int interval = Sound::length[sound];
213 /* add a small delay server side only */
214 if (Constants::server)
215 interval += Constants::tick;
216 timer->setInterval(interval);
217 connect(timer, SIGNAL(timeout()), this, SLOT(finished_ex()));
218 timer->start();
219 }
207} 220}
208 221
209/* this is a simple hack to check if phonon can actually play sounds.. */ 222/* this is a simple hack to check if phonon can actually play sounds.. */
@@ -227,6 +240,11 @@ void AudioPlayer::test(QFile *testsound)
227 clear(); 240 clear();
228} 241}
229 242
243void AudioPlayer::finished_ex()
244{
245 emit finished();
246}
247
230void AudioPlayer::stateChanged_ex(Phonon::State newstate, Phonon::State /* oldstate */) 248void AudioPlayer::stateChanged_ex(Phonon::State newstate, Phonon::State /* oldstate */)
231{ 249{
232 if (newstate != Phonon::ErrorState) 250 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
23 Die, 23 Die,
24 Ambient 24 Ambient
25 }; 25 };
26
27 const unsigned int length[] = {
28 4310, 2090, 570, 570, 1720
29 };
26}; 30};
27 31
28/* --------------------------------------------------------------- */ 32/* --------------------------------------------------------------- */
@@ -50,7 +54,7 @@ public:
50 bool isMuted() const; 54 bool isMuted() const;
51 void setLoop(Sound::Type sound); 55 void setLoop(Sound::Type sound);
52 void play(); 56 void play();
53 void play(Sound::Type sound); 57 void play(Sound::Type sound, bool wait = false);
54 58
55protected: 59protected:
56 void test(QFile *testsound); 60 void test(QFile *testsound);
@@ -60,6 +64,7 @@ public slots:
60 void loopEnqueue(); 64 void loopEnqueue();
61 65
62protected slots: 66protected slots:
67 void finished_ex();
63 void testFinished(); 68 void testFinished();
64 void stateChanged_ex(Phonon::State newstate, Phonon::State oldstate); 69 void stateChanged_ex(Phonon::State newstate, Phonon::State oldstate);
65 70
@@ -116,7 +121,7 @@ public:
116 void clearQueue() const; 121 void clearQueue() const;
117 122
118 AudioPlayer *audioPlayer(); 123 AudioPlayer *audioPlayer();
119 void play(Sound::Type sound); 124 void play(Sound::Type sound, bool wait = false);
120 void enqueue(Sound::Type sound); 125 void enqueue(Sound::Type sound);
121 126
122 void registerAudioPlayer(AudioPlayer *player); 127 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)
36 setSprite(neighbours * Constants::sprite_offset, 0, Constants::field_size.width, Constants::field_size.height); 36 setSprite(neighbours * Constants::sprite_offset, 0, Constants::field_size.width, Constants::field_size.height);
37} 37}
38 38
39bool Block::checkEnter(Actor *actor) 39bool Block::checkEnter(Actor * /* actor */)
40{ 40{
41 if (m_color == Color::none) 41 if (m_color == Color::none)
42 return false; 42 return false;
43 return (m_color == actor->color()); 43 return true;
44} 44}
45 45
46bool Block::enter(Actor *actor) 46GameEntity::EnteredState Block::enter(Actor *actor)
47{ 47{
48 if (m_color != actor->color()) 48 if (m_color != Color::none && m_color != actor->color())
49 { 49 return DestroyedActor;
50 //TODO: actor dies + game ends 50 return Nothing;
51 } 51}
52 return true; 52
53void Block::onDie(Actor *actor)
54{
55 actor->die();
53} 56}
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:
31 unsigned int neighbours(); 31 unsigned int neighbours();
32 void setNeighbours(unsigned int neighbours); 32 void setNeighbours(unsigned int neighbours);
33 virtual bool checkEnter(Actor *actor); 33 virtual bool checkEnter(Actor *actor);
34 virtual bool enter(Actor *actor); 34 virtual EnteredState enter(Actor *actor);
35 virtual void onDie(Actor *);
35 36
36private: 37private:
37 // map for saving QPixmaps for reuse 38 // 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)
26 setSprite(rand * 20 + Constants::sprite_margin, Constants::sprite_margin, Constants::field_size.width, Constants::field_size.height); 26 setSprite(rand * 20 + Constants::sprite_margin, Constants::sprite_margin, Constants::field_size.width, Constants::field_size.height);
27} 27}
28 28
29bool BonusPoint::enter(Actor *actor) 29GameEntity::EnteredState BonusPoint::enter(Actor *actor)
30{ 30{
31 actor->addRoundPoints(Constants::Game::bonus_point_value); 31 actor->addRoundPoints(Constants::Game::bonus_point_value);
32 m_eaten = true; 32 return DestroyedEntity;
33 return false;
34} 33}
35 34
36void BonusPoint::onDie(Actor *actor) 35void 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:
17 virtual ~BonusPoint() 17 virtual ~BonusPoint()
18 {}; 18 {};
19 19
20 virtual bool enter(Actor *actor); 20 virtual EnteredState enter(Actor *actor);
21 virtual void onDie(Actor *actor); 21 virtual void onDie(Actor *actor);
22}; 22};
23 23
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
83 const field_t bonuspoint = (1 << 6); 83 const field_t bonuspoint = (1 << 6);
84 const field_t pacman = (1 << 7); 84 const field_t pacman = (1 << 7);
85 const field_t empty = (1 << 8); // explicit empty for update 85 const field_t empty = (1 << 8); // explicit empty for update
86 const field_t death = (1 << 9);
86 87
87 const field_t direction_none = 0; 88 const field_t direction_none = 0;
88 const field_t direction_left = (1 << 9); 89 const field_t direction_left = (1 << 10);
89 const field_t direction_right = (1 << 10); 90 const field_t direction_right = (1 << 11);
90 const field_t direction_up = (1 << 11); 91 const field_t direction_up = (1 << 12);
91 const field_t direction_down = (1 << 12); 92 const field_t direction_down = (1 << 13);
92 93
93 const mask_t color_mask = Color::none | Color::red | Color::blue | Color::green | Color::yellow; 94 const mask_t color_mask = Color::none | Color::red | Color::blue | Color::green | Color::yellow;
94 const mask_t type_mask = block | bonuspoint; 95 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 @@
1#include "gameentity.h" 1#include "gameentity.h"
2 2
3GameEntity::GameEntity(Color::Color color, QGraphicsItem *parent) 3GameEntity::GameEntity(Color::Color color, QGraphicsItem *parent)
4 : PixmapItem(parent), m_type(Type), m_eaten(false), m_color(color) 4 : PixmapItem(parent), m_type(Type), m_color(color)
5{} 5{}
6 6
7GameEntity::GameEntity(QGraphicsItem *parent) 7GameEntity::GameEntity(QGraphicsItem *parent)
8 : PixmapItem(parent), m_type(Type), m_eaten(false), m_color(Color::none) 8 : PixmapItem(parent), m_type(Type), m_color(Color::none)
9{} 9{}
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:
20 Type = UserType + 1 20 Type = UserType + 1
21 }; 21 };
22 22
23 enum EnteredState
24 {
25 Nothing,
26 DestroyedEntity,
27 DestroyedActor
28 };
29
23public: 30public:
24 GameEntity(Color::Color color = Color::none, QGraphicsItem *parent = 0); 31 GameEntity(Color::Color color = Color::none, QGraphicsItem *parent = 0);
25 GameEntity(QGraphicsItem *parent); 32 GameEntity(QGraphicsItem *parent);
@@ -41,18 +48,10 @@ public:
41 /* performs action when this actor acctually enters 48 /* performs action when this actor acctually enters
42 * returns whether this entity survives the entering 49 * returns whether this entity survives the entering
43 */ 50 */
44 virtual bool enter(Actor *) 51 virtual EnteredState enter(Actor *)
45 { 52 {
46 /* default to no action/survive */ 53 /* default to no action/survive */
47 return true; 54 return Nothing;
48 }
49
50 /* check whether this entity is regarded as eaten
51 * (and can be removed in the next tick)
52 */
53 virtual bool eaten()
54 {
55 return m_eaten;
56 } 55 }
57 56
58 /* called when an instance acctually dies for creating effects */ 57 /* called when an instance acctually dies for creating effects */
@@ -67,7 +66,6 @@ public:
67 66
68protected: 67protected:
69 int m_type; 68 int m_type;
70 bool m_eaten;
71 Color::Color m_color; 69 Color::Color m_color;
72}; 70};
73 71
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)
33 m_socket->waitForReadyRead(); 33 m_socket->waitForReadyRead();
34 tick(); 34 tick();
35 35
36 connect(m_socket, SIGNAL(readyRead()), this, SLOT(tick()));
37 qDebug() << "[Connect] mycolor=" << m_scene->color(); 36 qDebug() << "[Connect] mycolor=" << m_scene->color();
38 37 connect(m_socket, SIGNAL(readyRead()), this, SLOT(tick()));
39 //TODO: play intro as soon as there are enough players
40 //connect(AudioPlayer::self(), SIGNAL(finished()), this, SLOT(startGame()));
41 //AudioPlayer::self()->play(AudioPlayer::Intro);
42 startGame();
43} 38}
44 39
45bool MainWidget::connected() 40bool MainWidget::connected()
@@ -146,6 +141,7 @@ void MainWidget::tick()
146 Q_ASSERT(worked); 141 Q_ASSERT(worked);
147 Q_UNUSED(worked); 142 Q_UNUSED(worked);
148 143
144 /* eating order data set inidicates a new round */
149 if (m_updatepacket.eating_order_size() > 0) 145 if (m_updatepacket.eating_order_size() > 0)
150 { 146 {
151 Q_ASSERT(m_scene != NULL); 147 Q_ASSERT(m_scene != NULL);
@@ -156,6 +152,11 @@ void MainWidget::tick()
156 for(int i = 0; i < m_updatepacket.eating_order_size(); ++i) 152 for(int i = 0; i < m_updatepacket.eating_order_size(); ++i)
157 order.append(static_cast<Color::Color>(m_updatepacket.eating_order(i) & Transmission::color_mask)); 153 order.append(static_cast<Color::Color>(m_updatepacket.eating_order(i) & Transmission::color_mask));
158 m_scene->setEatingOrder(order); 154 m_scene->setEatingOrder(order);
155
156 /* stop and restart game */
157 stopGame();
158 connect(AudioManager::self()->audioPlayer(), SIGNAL(finished()), this, SLOT(startGame()));
159 AudioManager::self()->play(Sound::Intro, true);
159 } 160 }
160 161
161 Transmission::map_t map = Util::createUninitialisedMap(); 162 Transmission::map_t map = Util::createUninitialisedMap();
@@ -177,8 +178,6 @@ void MainWidget::tick()
177 178
178void MainWidget::keyPressEvent(QKeyEvent* event) 179void MainWidget::keyPressEvent(QKeyEvent* event)
179{ 180{
180 if (!m_running)
181 return;
182 if (event->isAutoRepeat()) 181 if (event->isAutoRepeat())
183 return; 182 return;
184 183
@@ -194,8 +193,6 @@ void MainWidget::keyPressEvent(QKeyEvent* event)
194 193
195void MainWidget::sendKeyUpdate() 194void MainWidget::sendKeyUpdate()
196{ 195{
197 if (!m_running)
198 return;
199 if (m_currentKey == Transmission::direction_none) 196 if (m_currentKey == Transmission::direction_none)
200 return; 197 return;
201 qDebug() << "[SendKey] key=" << m_currentKey; 198 qDebug() << "[SendKey] key=" << m_currentKey;
@@ -206,10 +203,8 @@ void MainWidget::sendKeyUpdate()
206 203
207void MainWidget::keyReleaseEvent(QKeyEvent* event) 204void MainWidget::keyReleaseEvent(QKeyEvent* event)
208{ 205{
209 if (!m_running)
210 return;
211 if (event->isAutoRepeat()) 206 if (event->isAutoRepeat())
212 return; 207 return;
213 208
214 QWidget::keyReleaseEvent(event); 209 QWidget::keyReleaseEvent(event);
215 m_currentKey = Transmission::none; 210 m_currentKey = Transmission::none;
@@ -218,10 +213,18 @@ void MainWidget::keyReleaseEvent(QKeyEvent* event)
218 213
219void MainWidget::startGame() 214void MainWidget::startGame()
220{ 215{
216 disconnect(AudioManager::self()->audioPlayer(), NULL, this, SLOT(startGame()));
221 m_running = true; 217 m_running = true;
218 sendKeyUpdate();
222 m_ambientPlayer->play(); 219 m_ambientPlayer->play();
223} 220}
224 221
222void MainWidget::stopGame()
223{
224 m_running = false;
225 m_ambientPlayer->pause();
226}
227
225void MainWidget::setAmbientMuted(bool muted) 228void MainWidget::setAmbientMuted(bool muted)
226{ 229{
227 m_ambientPlayer->setMuted(muted); 230 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:
28 28
29private slots: 29private slots:
30 void startGame(); 30 void startGame();
31 void stopGame();
31 void playerScoreClicked(); 32 void playerScoreClicked();
32 void tick(); 33 void tick();
33 void sendKeyUpdate(); 34 void sendKeyUpdate();
diff --git a/pacman-c++/pics/actor1.png b/pacman-c++/pics/actor1.png
index ae9f172..5a37b4f 100644
--- a/pacman-c++/pics/actor1.png
+++ b/pacman-c++/pics/actor1.png
Binary files differ
diff --git a/pacman-c++/pics/actor2.png b/pacman-c++/pics/actor2.png
index 07ecb3f..736a6e7 100644
--- a/pacman-c++/pics/actor2.png
+++ b/pacman-c++/pics/actor2.png
Binary files differ
diff --git a/pacman-c++/pics/actor3.png b/pacman-c++/pics/actor3.png
index 486fd37..f963cff 100644
--- a/pacman-c++/pics/actor3.png
+++ b/pacman-c++/pics/actor3.png
Binary files differ
diff --git a/pacman-c++/pics/actor4.png b/pacman-c++/pics/actor4.png
index 9684fc0..e500dc5 100644
--- a/pacman-c++/pics/actor4.png
+++ b/pacman-c++/pics/actor4.png
Binary files 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)
21 setPixmap(*pixmap); 21 setPixmap(*pixmap);
22} 22}
23 23
24bool Point::enter(Actor *actor) 24GameEntity::EnteredState Point::enter(Actor *actor)
25{ 25{
26 actor->addRoundPoints(Constants::Game::point_value); 26 actor->addRoundPoints(Constants::Game::point_value);
27 m_eaten = true; 27 return DestroyedEntity;
28 return false;
29} 28}
30 29
31void Point::onDie(Actor *actor) 30void 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:
17 virtual ~Point() 17 virtual ~Point()
18 {}; 18 {};
19 19
20 virtual bool enter(Actor *actor); 20 virtual EnteredState enter(Actor *actor);
21 virtual void onDie(Actor *actor); 21 virtual void onDie(Actor *actor);
22}; 22};
23 23
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)
20 20
21void SceneHolder::reset() 21void SceneHolder::reset()
22{ 22{
23 /* reset actor directions */ 23 processDelayedItems();
24
25 /* remove actors from scene so they don't get deleted during clear */
24 foreach(Actor *actor, m_actors) 26 foreach(Actor *actor, m_actors)
25 actor->resetDirection(); 27 {
28 actor->resetAnimation();
29 removeItem(actor);
30 }
31
32 /* clear our stuff */
33 clear();
34 m_pointsLeft = 0;
35 for (int i = 0; i < visualMap.size(); ++i)
36 {
37 visualMap[i].clear();
38 visualMap[i].resize(Constants::map_size.height);
39 }
40
41 /* add actors again */
42 foreach(Actor *actor, m_actors)
43 addItem(actor);
26} 44}
27 45
28void SceneHolder::updateMap(const Transmission::map_t& map) 46void SceneHolder::processDelayedItems()
29{ 47{
30 /* remove items that got marked for removal from scene */ 48 /* remove items that got marked for removal from scene */
31 QMutableListIterator<GameEntity *> i(m_oldItems); 49 foreach(GameEntity *item, m_oldItems)
32 while(i.hasNext())
33 { 50 {
34 i.next();
35 GameEntity *item = i.value();
36 removeItem(item); 51 removeItem(item);
37 i.remove();
38 delete item; 52 delete item;
39 } 53 }
54 m_oldItems.clear();
55
56 /* process death */
57 foreach(const Color::Color color, m_death.keys())
58 {
59 Q_ASSERT(m_death[color] != NULL);
60 m_death[color]->onDie(m_actors[color]);
61 }
62 m_death.clear();
63}
64
65void SceneHolder::updateMap(const Transmission::map_t& map)
66{
67 processDelayedItems();
40 68
41 /* process update */ 69 /* process update */
42 for (unsigned int x = 0; x < Constants::map_size.width; ++x) 70 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
66 if (cur & Transmission::empty) 94 if (cur & Transmission::empty)
67 { 95 {
68 GameEntity *oldItem = visualMap[x][y]; 96 GameEntity *oldItem = visualMap[x][y];
69 /* special handling for purging field 97 /* special handling for purging field */
70 */
71 if (oldItem != NULL) 98 if (oldItem != NULL)
72 { 99 {
100 /* remove item from visualmap and register item for removal in next update */
73 visualMap[x][y] = NULL; 101 visualMap[x][y] = NULL;
74 Actor *actor = NULL; 102 m_oldItems.append(oldItem);
75 foreach (Actor *tmp, m_actors)
76 {
77 if (cur & tmp->color())
78 {
79 actor = tmp;
80 break;
81 }
82 }
83 103
84 /* an item must be removed by an actor */ 104 /* an item must be removed by an actor */
105 Actor *actor = m_actors[color];
85 if (actor == NULL) 106 if (actor == NULL)
86 Q_ASSERT(false); 107 Q_ASSERT(false);
87 oldItem->onDie(actor); 108 oldItem->onDie(actor);
88
89 /* register item for removal in next update */
90 m_oldItems.append(oldItem);
91 } 109 }
92 } 110 }
93 111
@@ -165,6 +183,10 @@ void SceneHolder::updateMap(const Transmission::map_t& map, const unsigned int x
165 qDebug() << "[SceneUpdate] actor moves: color=" << color 183 qDebug() << "[SceneUpdate] actor moves: color=" << color
166 << "direction=" << direction << "newpos=" << QPoint(x, y); 184 << "direction=" << direction << "newpos=" << QPoint(x, y);
167 } 185 }
186
187
188 if (cur & Transmission::death)
189 m_death[color] = visualMap[x][y];
168 } 190 }
169 191
170 if (cur & Transmission::empty) 192 if (cur & Transmission::empty)
@@ -221,16 +243,6 @@ QList<Color::Color> &SceneHolder::eatingOrder()
221 return m_eatingorder; 243 return m_eatingorder;
222} 244}
223 245
224void SceneHolder::removeActors()
225{
226 foreach(Actor *actor, m_actors)
227 {
228 removeItem(actor);
229 delete actor;
230 }
231 m_actors.clear();
232}
233
234QPoint SceneHolder::mapPositionToCoord(unsigned int x, unsigned int y) 246QPoint SceneHolder::mapPositionToCoord(unsigned int x, unsigned int y)
235{ 247{
236 return QPoint(x * Constants::field_size.width, y * Constants::field_size.height); 248 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:
24 Color::Color color(); 24 Color::Color color();
25 void setEatingOrder(QList<Color::Color> &order); 25 void setEatingOrder(QList<Color::Color> &order);
26 QList<Color::Color> &eatingOrder(); 26 QList<Color::Color> &eatingOrder();
27 void removeActors();
28 27
29signals: 28signals:
30 void allPointsRemoved(); 29 void allPointsRemoved();
@@ -33,6 +32,8 @@ private slots:
33 void decrementPoints(); 32 void decrementPoints();
34 33
35protected: 34protected:
35 /* process items that got delayed by one tick */
36 void processDelayedItems();
36 /* data conversion */ 37 /* data conversion */
37 QPoint mapPositionToCoord(unsigned int x, unsigned int y); 38 QPoint mapPositionToCoord(unsigned int x, unsigned int y);
38 QPoint mapPositionToCoord(QPoint point); 39 QPoint mapPositionToCoord(QPoint point);
@@ -50,6 +51,7 @@ protected:
50 * must be remove one tick later 51 * must be remove one tick later
51 */ 52 */
52 QList<GameEntity *> m_oldItems; 53 QList<GameEntity *> m_oldItems;
54 QMap<Color::Color, GameEntity *> m_death;
53 55
54 /* my local color */ 56 /* my local color */
55 Color::Color m_color; 57 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 @@
8#include <QtNetwork/QTcpServer> 8#include <QtNetwork/QTcpServer>
9#include <QtNetwork/QTcpSocket> 9#include <QtNetwork/QTcpSocket>
10#include <QTextStream> 10#include <QTextStream>
11#include <sys/types.h>
11 12
12Server::Server(QWidget *parent) 13Server::Server(QWidget *parent)
13 : SceneHolder(parent), m_bindaddress(QHostAddress::Any), 14 : SceneHolder(parent), m_bindaddress(QHostAddress::Any),
14 m_port(Constants::Networking::port), m_numbots(0), 15 m_port(Constants::Networking::port), m_numbots(0),
15 m_rounds(3), m_curRound(0), m_roundFinished(false) 16 m_rounds(3), m_curRound(0), m_running(false), m_finishRound(false)
16{ 17{
17 /* determine max players by using order array */ 18 /* determine max players by using order array */
18 for(m_maxplayers = 0; Color::order[m_maxplayers] != Color::none; ++m_maxplayers); 19 for(m_maxplayers = 0; Color::order[m_maxplayers] != Color::none; ++m_maxplayers);
@@ -36,54 +37,43 @@ bool Server::run()
36 if (!waitForClientConnections()) 37 if (!waitForClientConnections())
37 return false; 38 return false;
38 39
39 connect(this, SIGNAL(allPointsRemoved()), this, SLOT(setRoundFinished())); 40 connect(this, SIGNAL(allPointsRemoved()), this, SLOT(setFinishRound()));
40 initRoundMap(); 41 initRoundMap();
41 return true; 42 return true;
42} 43}
43 44
44void Server::tick() 45void Server::tick()
45{ 46{
46 //qDebug() << "[Tick] Doing server update"; 47 qDebug() << "[Tick] Doing server update";
47 if (m_roundFinished) 48 if (m_finishRound)
49 stopGame(true);
50 if (!m_running)
48 { 51 {
49 // TODO: call this when a pacman get's eaten 52 Transmission::map_t map = Util::createEmptyMap();
50 /* first finish previous round */ 53 sendUpdate(map);
51 foreach(Actor *actor, m_actors) 54 Util::deleteMap(map);
52 actor->finishRound(); 55 return;
53
54 ++m_curRound;
55 if(m_curRound < m_rounds)
56 initRoundMap();
57 else
58 {
59 /* end of game */
60 qDebug() << "All round finished. Exiting...";
61 m_tickTimer->stop();
62 qApp->quit();
63 }
64 } 56 }
65 else
66 {
67 /* let the bots move */
68 foreach (Color::Color color, m_bots)
69 botCalculate(m_actors[color]);
70 57
71 /* move on the virtual map */ 58 /* let the bots move */
72 Transmission::map_t map = calculateUpdates(); 59 foreach (Color::Color color, m_bots)
73 updateMap(map); 60 botCalculate(m_actors[color]);
74 61
75 /* add a random bonus point */ 62 /* move on the virtual map */
76 QPoint pos = addRandomPoint(map, Transmission::bonuspoint); 63 Transmission::map_t map = calculateUpdates();
77 if (!pos.isNull()) 64 updateMap(map);
78 updateMap(map, pos.x(), pos.y());
79 65
80 /* add/remove random colorized block */ 66 /* add a random bonus point */
81 if (this->property("coloredblocks").toBool()) 67 QPoint pos = addRandomPoint(map, Transmission::bonuspoint);
82 colorizeBlocks(map); 68 if (!pos.isNull())
69 updateMap(map, pos.x(), pos.y());
83 70
84 sendUpdate(map); 71 /* add/remove random colorized block */
85 Util::deleteMap(map); 72 if (this->property("coloredblocks").toBool())
86 } 73 colorizeBlocks(map);
74
75 sendUpdate(map);
76 Util::deleteMap(map);
87} 77}
88 78
89Transmission::map_t Server::calculateUpdates() 79Transmission::map_t Server::calculateUpdates()
@@ -94,14 +84,15 @@ Transmission::map_t Server::calculateUpdates()
94 while (i.hasNext()) 84 while (i.hasNext())
95 { 85 {
96 i.next(); 86 i.next();
97 Actor *actor = m_actors.value(i.key()); 87 Color::Color color = i.key();
88 Actor *actor = m_actors[color];
98 QPoint mapPosition = CoordToMapPosition(actor->pos().toPoint()); 89 QPoint mapPosition = CoordToMapPosition(actor->pos().toPoint());
99 Actor::Movement direction = i.value(); 90 Actor::Movement direction = i.value();
100 int turn = 0; 91 int turn = 0;
101 92
102invalid_direction: 93invalid_direction:
103 ++turn; 94 ++turn;
104 qDebug() << "[Calc] Actor wants to move: color=" << i.key() 95 qDebug() << "[Calc] Actor wants to move: color=" << color
105 << "pos=" << mapPosition << "direction=" << direction; 96 << "pos=" << mapPosition << "direction=" << direction;
106 97
107 QPoint newMapPosition = mapPosition + Actor::movementToPoint(direction); 98 QPoint newMapPosition = mapPosition + Actor::movementToPoint(direction);
@@ -132,10 +123,15 @@ invalid_direction:
132 else 123 else
133 { 124 {
134 /* apply actions of entering this field */ 125 /* apply actions of entering this field */
135 bool survive = item->enter(actor); 126 GameEntity::EnteredState survive = item->enter(actor);
136 if (!survive) 127 if (survive == GameEntity::DestroyedEntity)
137 {
138 map[newMapPosition.x()][newMapPosition.y()] = Transmission::empty | actor->color(); 128 map[newMapPosition.x()][newMapPosition.y()] = Transmission::empty | actor->color();
129 else if (survive == GameEntity::DestroyedActor)
130 {
131 m_actors[item->color()]->addRoundPoints(actor->getRoundPoints());
132 actor->finishRound(true);
133 map[newMapPosition.x()][newMapPosition.y()] = Transmission::death | actor->color();
134 setFinishRound();
139 } 135 }
140 } 136 }
141 } 137 }
@@ -161,7 +157,7 @@ invalid_direction:
161 } 157 }
162 158
163 map[newMapPosition.x()][newMapPosition.y()] |= Transmission::pacman | 159 map[newMapPosition.x()][newMapPosition.y()] |= Transmission::pacman |
164 i.key() | Util::actorMovementToTransmission(direction); 160 color | Util::actorMovementToTransmission(direction);
165 161
166 /* DEBUG: uncomments to disable auto-movement */ 162 /* DEBUG: uncomments to disable auto-movement */
167 //direction = Actor::None; 163 //direction = Actor::None;
@@ -169,7 +165,7 @@ invalid_direction:
169 if (direction == Actor::None) 165 if (direction == Actor::None)
170 { 166 {
171 /* set actor to non-moving */ 167 /* set actor to non-moving */
172 m_actorMovements[i.key()] = Actor::None; 168 m_actorMovements[color] = Actor::None;
173 i.remove(); 169 i.remove();
174 } 170 }
175 } 171 }
@@ -228,11 +224,12 @@ void Server::colorizeBlocks(Transmission::map_t map)
228 i.setValue(--val); 224 i.setValue(--val);
229 else 225 else
230 { 226 {
227 QPoint block = i.key();
231 /* check for actor collision */ 228 /* check for actor collision */
232 bool skip = false; 229 bool skip = false;
233 foreach (Actor *actor, m_actors) 230 foreach (Actor *actor, m_actors)
234 { 231 {
235 if (CoordToMapPosition(actor->pos().toPoint()) == i.key()) 232 if (CoordToMapPosition(actor->pos().toPoint()) == block)
236 skip = true; 233 skip = true;
237 if (skip) 234 if (skip)
238 break; 235 break;
@@ -240,7 +237,6 @@ void Server::colorizeBlocks(Transmission::map_t map)
240 if (skip) 237 if (skip)
241 continue; 238 continue;
242 239
243 QPoint block = i.key();
244 map[block.x()][block.y()] |= Transmission::block | Color::none; 240 map[block.x()][block.y()] |= Transmission::block | Color::none;
245 updateMap(map, block.x(), block.y()); 241 updateMap(map, block.x(), block.y());
246 m_blocks.append(block); 242 m_blocks.append(block);
@@ -510,16 +506,14 @@ void Server::keyPressUpdate()
510 } 506 }
511} 507}
512 508
513void Server::setRoundFinished(bool value)
514{
515 m_roundFinished = value;
516}
517
518void Server::initRoundMap() 509void Server::initRoundMap()
519{ 510{
520 qDebug() << "[initRoundMap] New round starts..."; 511 qDebug() << "[initRoundMap] New round starts...";
521 m_tickTimer->stop(); 512 m_tickTimer->stop();
522 513
514 /* reset scene and clean up items */
515 reset();
516
523 /* create new map */ 517 /* create new map */
524 Transmission::map_t map = Util::createDemoMap(); 518 Transmission::map_t map = Util::createDemoMap();
525 Util::placeActors(map, m_maxplayers, Color::order); 519 Util::placeActors(map, m_maxplayers, Color::order);
@@ -542,11 +536,54 @@ void Server::initRoundMap()
542 Util::deleteMap(map); 536 Util::deleteMap(map);
543 map = NULL; 537 map = NULL;
544 538
545 m_roundFinished = false;
546 m_actorMovements.clear(); 539 m_actorMovements.clear();
540
541 disconnect(AudioManager::self()->audioPlayer(), NULL, this, NULL);
542 connect(AudioManager::self()->audioPlayer(), SIGNAL(finished()), this, SLOT(startGame()));
543 AudioManager::self()->play(Sound::Intro, true);
547 m_tickTimer->start(); 544 m_tickTimer->start();
548} 545}
549 546
547void Server::startGame()
548{
549 m_running = true;
550}
551
552void Server::stopGame(bool delay)
553{
554 /* first finish previous round */
555 foreach(Actor *actor, m_actors)
556 actor->finishRound();
557 m_finishRound = false;
558 m_running = false;
559
560 /* add delay if requested */
561 if (delay)
562 {
563 disconnect(AudioManager::self()->audioPlayer(), NULL, this, NULL);
564 connect(AudioManager::self()->audioPlayer(), SIGNAL(finished()), this, SLOT(stopGame()));
565 AudioManager::self()->play(Sound::Die, true);
566 return;
567 }
568
569 /* do next-round work */
570 ++m_curRound;
571 if(m_rounds == 0 || m_curRound < m_rounds)
572 initRoundMap();
573 else
574 {
575 /* end of game */
576 qDebug() << "All round finished. Exiting...";
577 qApp->quit();
578 }
579}
580
581
582void Server::setFinishRound()
583{
584 m_finishRound = true;
585}
586
550bool Server::parseCommandline() 587bool Server::parseCommandline()
551{ 588{
552 AnyOption opt; 589 AnyOption opt;
@@ -583,7 +620,7 @@ bool Server::parseCommandline()
583 << " Disable random colorized blocks" << endl 620 << " Disable random colorized blocks" << endl
584 << endl; 621 << endl;
585 opt.setOption("rounds", 'r'); 622 opt.setOption("rounds", 'r');
586 out << " -r, --rounds [1..n]" << endl 623 out << " -r, --rounds [0 | 1..n]" << endl
587 << " Number of rounds to play" << endl 624 << " Number of rounds to play" << endl
588 << " Default: " << m_rounds << endl 625 << " Default: " << m_rounds << endl
589 << endl; 626 << 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:
40 void initRoundMap(); 40 void initRoundMap();
41 41
42protected slots: 42protected slots:
43 /* called when a round is finished */ 43 /* called when a round is started/finished */
44 void setRoundFinished(bool value = true); 44 void startGame();
45 void stopGame(bool delay = false);
46 void setFinishRound();
45 47
46protected: 48protected:
47 QMap<Color::Color, QTcpSocket *> m_clientConnections; 49 QMap<Color::Color, QTcpSocket *> m_clientConnections;
@@ -66,7 +68,8 @@ protected:
66 unsigned int m_rounds; 68 unsigned int m_rounds;
67 /* current round, starting at 0 */ 69 /* current round, starting at 0 */
68 unsigned int m_curRound; 70 unsigned int m_curRound;
69 bool m_roundFinished; 71 bool m_running;
72 bool m_finishRound;
70 73
71 QTimer *m_tickTimer; 74 QTimer *m_tickTimer;
72 75