2
* Copyright 2007-2008 Thomas Gallinari <tg8187@yahoo.fr>
3
* Copyright 2007-2008 Alexandre Galinier <alex.galinier@hotmail.com>
5
* This program is free software; you can redistribute it and/or
6
* modify it under the terms of the GNU General Public License as
7
* published by the Free Software Foundation; either version 2 of
8
* the License, or (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program. If not, see <http://www.gnu.org/licenses/>.
19
#include "gamescene.h"
26
GameScene::GameScene(Game* p_game) : m_game(p_game), m_kapmanItem(0), m_mazeItem(0) {
27
connect(p_game, SIGNAL(levelStarted(bool)), SLOT(intro(bool)));
28
connect(p_game, SIGNAL(gameStarted()), this, SLOT(start()));
29
connect(p_game, SIGNAL(pauseChanged(bool,bool)), this, SLOT(setPaused(bool,bool)));
30
connect(p_game, SIGNAL(elementEaten(qreal,qreal)), this, SLOT(hideElement(qreal,qreal)));
31
connect(p_game, SIGNAL(bonusOn()), this, SLOT(displayBonus()));
32
connect(p_game, SIGNAL(bonusOff()), this, SLOT(hideBonus()));
34
// Connection between Game and GameScene for the display of won points when a bonus or a ghost is eaten
35
connect(p_game, SIGNAL(pointsToDisplay(long,qreal,qreal)), this, SLOT(displayPoints(long,qreal,qreal)));
37
// Create the theme instance
38
m_theme = new KGameTheme();
41
m_renderer = new QSvgRenderer();
44
// Create the MazeItem
45
m_mazeItem = new MazeItem();
46
// Give the maze the shared renderer to avoid loading the whole SVG file again
47
m_mazeItem->setSharedRenderer(m_renderer);
48
// Set the element Id to the right value
49
m_mazeItem->setElementId("maze");
50
m_mazeItem->setZValue(-2);
52
// Create the KapmanItem
53
m_kapmanItem = new KapmanItem(p_game->getKapman());
54
m_kapmanItem->setSharedRenderer(m_renderer);
55
m_kapmanItem->setElementId("kapman_0");
56
// Corrects the position of the KapmanItem
57
m_kapmanItem->update(p_game->getKapman()->getX(), p_game->getKapman()->getY());
58
m_kapmanItem->setZValue(2);
59
// Stops the Kapman animation
60
m_kapmanItem->stopAnim();
62
// Create the GhostItems
63
for (int i = 0; i < p_game->getGhosts().size(); ++i) {
64
GhostItem* ghost = new GhostItem(p_game->getGhosts()[i]);
65
ghost->setSharedRenderer(m_renderer);
66
ghost->setElementId(p_game->getGhosts()[i]->getImageId());
67
ghost->update(p_game->getGhosts()[i]->getX(), p_game->getGhosts()[i]->getY());
68
// At the beginning, the ghosts are above the kapman because they eat him
70
m_ghostItems.append(ghost);
72
// Create the Pill and Energizer items
73
m_elementItems = new ElementItem**[m_game->getMaze()->getNbRows()];
74
for (int i = 0; i < m_game->getMaze()->getNbRows(); ++i) {
75
m_elementItems[i] = new ElementItem*[m_game->getMaze()->getNbColumns()];
76
for (int j = 0; j < m_game->getMaze()->getNbColumns(); ++j) {
77
if (m_game->getMaze()->getCell(i, j).getElement() != NULL) {
78
// Create the element and set the image
79
ElementItem* element = new ElementItem(m_game->getMaze()->getCell(i, j).getElement());
80
element->setSharedRenderer(m_renderer);
81
element->setElementId(m_game->getMaze()->getCell(i,j).getElement()->getImageId());
82
element->update(m_game->getMaze()->getCell(i, j).getElement()->getX(), m_game->getMaze()->getCell(i, j).getElement()->getY());
83
m_elementItems[i][j] = element;
85
m_elementItems[i][j] = NULL;
89
// Create the Bonus item
90
m_bonusItem = new ElementItem(m_game->getBonus());
91
m_bonusItem->setSharedRenderer(m_renderer);
92
m_bonusItem->setElementId("bonus1");
94
// All elements are created, update theme properties
96
updateThemeProperties();
98
// Create the introduction labels
99
m_introLabel = new QGraphicsTextItem(i18n("GET READY!!!"));
100
m_introLabel->setFont(QFont("Helvetica", 25, QFont::Bold, false));
101
m_introLabel->setDefaultTextColor(QColor("#FFFF00"));
102
m_introLabel->setZValue(4);
103
m_introLabel2 = new QGraphicsTextItem(i18n("Press any arrow key to start"));
104
m_introLabel2->setFont(QFont("Helvetica", 15, QFont::Bold, false));
105
m_introLabel2->setDefaultTextColor(QColor("#FFFF00"));
106
m_introLabel2->setZValue(4);
107
// Create the new level label
108
m_newLevelLabel = new QGraphicsTextItem();
109
m_newLevelLabel->setFont(QFont("Helvetica", 35, QFont::Bold, false));
110
m_newLevelLabel->setDefaultTextColor(QColor("#FFFF00"));
111
m_newLevelLabel->setZValue(4);
112
// Create the pause label
113
m_pauseLabel = new QGraphicsTextItem(i18n("PAUSED"));
114
m_pauseLabel->setFont(QFont("Helvetica", 35, QFont::Bold, false));
115
m_pauseLabel->setDefaultTextColor(QColor("#FFFF00"));
116
m_pauseLabel->setZValue(4);
118
// Display the MazeItem
120
// Display the KapmanItem
121
addItem(m_kapmanItem);
122
// Display each GhostItem
123
for (int i = 0; i < m_ghostItems.size(); ++i) {
124
addItem(m_ghostItems[i]);
126
// Display each Pill and Energizer item and introduction labels
130
GameScene::~GameScene() {
133
for (int i = 0; i < m_ghostItems.size(); ++i) {
134
delete m_ghostItems[i];
136
for (int i = 0; i < m_game->getMaze()->getNbRows();++i) {
137
for (int j = 0; j < m_game->getMaze()->getNbColumns(); ++j) {
138
if (m_elementItems[i][j] != NULL) {
139
delete m_elementItems[i][j];
142
delete[] m_elementItems[i];
144
delete[] m_elementItems;
147
delete m_introLabel2;
148
delete m_newLevelLabel;
154
Game* GameScene::getGame() const {
158
void GameScene::loadTheme() {
159
if (!m_theme->load(Settings::self()->theme())) {
162
if (!m_renderer->load(m_theme->graphics())) {
166
//Update elementIDs, theme properties
168
updateThemeProperties();
170
update(0, 0, width(), height());
172
// Update the theme config: if the default theme is selected, no theme entry is written -> the theme selector does not select the theme
173
Settings::self()->config()->group("General").writeEntry("Theme", Settings::self()->theme());
176
void GameScene::updateSvgIds() {
177
//Needed so new boundingRects() are read for all SVG elements after a theme change
178
// Sanity check, see if game elements already exist
179
if (!m_kapmanItem) return;
181
// Set the element Id to the right value
182
m_mazeItem->setElementId("maze");
184
// Create the KapmanItem
185
m_kapmanItem->setElementId("kapman_0");
186
// Corrects the position of the KapmanItem
187
m_kapmanItem->update(m_game->getKapman()->getX(), m_game->getKapman()->getY());
189
for (int i = 0; i < m_ghostItems.size(); ++i) {
190
GhostItem* ghost = m_ghostItems[i];
191
ghost->setElementId(m_game->getGhosts()[i]->getImageId());
192
ghost->update(m_game->getGhosts()[i]->getX(), m_game->getGhosts()[i]->getY());
194
for (int i = 0; i < m_game->getMaze()->getNbRows();++i) {
195
for (int j = 0; j < m_game->getMaze()->getNbColumns(); ++j) {
196
if (m_elementItems[i][j] != NULL) {
197
ElementItem* element = m_elementItems[i][j];
198
element->setElementId(m_game->getMaze()->getCell(i,j).getElement()->getImageId());
199
element->update(m_game->getMaze()->getCell(i, j).getElement()->getX(), m_game->getMaze()->getCell(i, j).getElement()->getY());
205
void GameScene::updateThemeProperties() {
206
// Sanity check, see if game elements already exist
207
if (!m_kapmanItem) return;
209
// Set the Rotation flag for KapmanItem
210
if (m_theme->themeProperty("RotateKapman")=="0") {
211
m_kapmanItem->setRotationFlag(false);
213
m_kapmanItem->setRotationFlag(true);
217
void GameScene::intro(const bool p_newLevel) {
218
// If a new level has begun
220
// Set each Pill and Energizer item to its original coordinates
221
for (int i = 0; i < m_game->getMaze()->getNbRows(); ++i) {
222
for (int j = 0; j < m_game->getMaze()->getNbColumns(); ++j) {
223
if (m_elementItems[i][j] != NULL) {
224
if (!items().contains(m_elementItems[i][j])) {
225
addItem(m_elementItems[i][j]);
230
// Display the new level label
231
m_newLevelLabel->setPlainText(i18nc("The number of the game level", "Level %1", m_game->getLevel()));
232
if (!items().contains(m_newLevelLabel)) {
233
addItem(m_newLevelLabel);
234
m_newLevelLabel->setPos((width() - m_newLevelLabel->boundingRect().width()) / 2, (height() - m_newLevelLabel->boundingRect().height()) / 2);
236
// Display the introduction label
237
if (!items().contains(m_introLabel2)) {
238
addItem(m_introLabel2);
239
m_introLabel2->setPos((width() - m_introLabel2->boundingRect().width()) / 2,
240
(height() - m_introLabel2->boundingRect().height() + m_newLevelLabel->boundingRect().height()) / 2);
243
// Display the introduction labels
244
if (!items().contains(m_introLabel)) {
245
addItem(m_introLabel);
246
m_introLabel->setPos((width() - m_introLabel->boundingRect().width()) / 2, (height() - m_introLabel->boundingRect().height()) / 2);
248
if (!items().contains(m_introLabel2)) {
249
addItem(m_introLabel2);
250
m_introLabel2->setPos((width() - m_introLabel2->boundingRect().width()) / 2,
251
(height() - m_introLabel2->boundingRect().height() + m_introLabel->boundingRect().height()) / 2);
256
void GameScene::start() {
257
// If the introduction and new level labels were displayed then remove them
258
if (items().contains(m_introLabel)) {
259
removeItem(m_introLabel);
261
if (items().contains(m_introLabel2)) {
262
removeItem(m_introLabel2);
264
if (items().contains(m_newLevelLabel)) {
265
removeItem(m_newLevelLabel);
269
void GameScene::setPaused(const bool p_pause, const bool p_fromUser) {
270
// If the game has paused
272
// If the pause is due to an action from the user
274
// If the label was not displayed yet
275
if (!items().contains(m_pauseLabel)) {
276
// FIXME: Hack to remove labels when pausing game while init labels are shown (icwiener)
277
// This should be done cleaner
278
// FIXME #2: start() is a misleading method name ...
280
// Display the pause label
281
addItem(m_pauseLabel);
282
m_pauseLabel->setPos((width() - m_pauseLabel->boundingRect().width()) / 2, (height() - m_pauseLabel->boundingRect().height()) / 2);
285
// Stop kapman animation
286
m_kapmanItem->pauseAnim();
287
} else { // If the game has resumed
288
// If the pause was due to an action from the user
290
// If the label was displayed
291
if (items().contains(m_pauseLabel)) {
292
removeItem(m_pauseLabel);
295
// Resume kapman animation
296
m_kapmanItem->resumeAnim();
300
void GameScene::hideElement(const qreal p_x, const qreal p_y) {
301
if (items().contains(m_elementItems[(int)((p_y - (Cell::SIZE * 0.5)) / Cell::SIZE)][(int)((p_x - (Cell::SIZE * 0.5)) / Cell::SIZE)])) {
302
removeItem(m_elementItems[(int)((p_y - (Cell::SIZE * 0.5)) / Cell::SIZE)][(int)((p_x - (Cell::SIZE * 0.5)) / Cell::SIZE)]);
306
void GameScene::displayBonus() {
307
if (!items().contains(m_bonusItem)) {
308
switch (m_game->getLevel()) {
310
m_bonusItem->setElementId("bonus1");
313
m_bonusItem->setElementId("bonus2");
316
m_bonusItem->setElementId("bonus3");
319
m_bonusItem->setElementId("bonus4");
322
m_bonusItem->setElementId("bonus5");
325
m_bonusItem->setElementId("bonus6");
328
m_bonusItem->setElementId("bonus7");
331
m_bonusItem->update(m_game->getBonus()->getX(), m_game->getBonus()->getY());
332
addItem(m_bonusItem);
336
void GameScene::hideBonus() {
337
if (items().contains(m_bonusItem)) {
338
removeItem(m_bonusItem);
343
void GameScene::displayPoints(long p_wonPoints, qreal p_xPos, qreal p_yPos) {
344
// Launch a singleShot timer
345
QTimer::singleShot(1000, this, SLOT(hidePoints()));
347
// Add a label in the list of won points Labels
348
m_wonPointsLabels.prepend(new QGraphicsTextItem(QString::number(p_wonPoints)));
349
addItem(m_wonPointsLabels.first());
351
// Temporary reference to the first item in the list
352
QGraphicsTextItem* tempRef = m_wonPointsLabels.first();
354
// Positioning and customization of the point label
355
tempRef->setDefaultTextColor(QColor("#FFFF00"));
356
tempRef->setFont(QFont("Helvetica", 15, QFont::Normal, false));
357
tempRef->setPos(p_xPos-(tempRef->boundingRect().width() / 2), p_yPos-(tempRef->boundingRect().height() / 2));
358
tempRef->setZValue(-1);
361
void GameScene::hidePoints() {
362
// Remove the oldest item of the list from the scene
363
removeItem(m_wonPointsLabels.last());
364
// Remove the oldest item from the list
365
delete m_wonPointsLabels.takeLast();