1
/***************************************************************************
2
* KBlocks, a falling blocks game for KDE *
3
* Copyright (C) 2010 Mauricio Piacentini <mauricio@tabuleiro.com> *
4
* Zhongjie Cai <squall.leonhart.cai@gmail.com> *
6
* This program is free software; you can redistribute it and/or modify *
7
* it under the terms of the GNU General Public License as published by *
8
* the Free Software Foundation; either version 2 of the License, or *
9
* (at your option) any later version. *
10
***************************************************************************/
11
#include "KBlocksScene.h"
15
#include <QVarLengthArray>
17
KBlocksScene::KBlocksScene(GameLogicInterface * p, int capacity)
21
mSnapshotMode = false;
24
mMaxCapacity = capacity;
25
mSceneGamesPerLine = 4;
26
mGameAnimEnabled = true;
27
mWaitForAllUpdate = false;
29
maGroupList = new KBlocksItemGroup*[capacity]();
30
maGameScoreList = new KBlocksScore*[capacity]();
31
maGameReadySignal = new bool[capacity]();
33
QString themeFile(Settings::theme());
34
mpGrafx = new KBlocksGraphics(themeFile);
35
mpSnd = new KBlocksSound(themeFile);
37
int width = (capacity >= mSceneGamesPerLine) ? mSceneGamesPerLine : (capacity % mSceneGamesPerLine);
38
int height = (int)(capacity / (mSceneGamesPerLine + 1)) + 1;
39
setSceneRect(0, 0, mpGrafx->m_View_Size_Width * width,
40
mpGrafx->m_View_Size_Height * height);
42
setItemIndexMethod(NoIndex);
45
mUpdateTimer.setInterval(mUpdateInterval);
46
connect(&mUpdateTimer, SIGNAL(timeout()), SLOT(updateGame()));
50
KBlocksScene::~KBlocksScene()
52
delete [] maGameReadySignal;
53
delete [] maGameScoreList;
54
delete [] maGroupList;
60
KBlocksItemGroup* KBlocksScene::getItemGroup(int index)
62
return maGroupList[index];
65
KBlocksScore* KBlocksScene::getScoreHandler(int index)
67
return maGameScoreList[index];
70
void KBlocksScene::createGameItemGroups(int groupCount, bool snapshotMode)
72
if (groupCount > mMaxCapacity)
74
mGroupCount = mMaxCapacity;
76
mGroupCount = groupCount;
77
mSnapshotMode = snapshotMode;
80
for(int i = 0; i < mGroupCount; i++)
82
maGroupList[i] = new KBlocksItemGroup(i, mpGameLogic->getSingleGame(i), mpGrafx, mpSnd, snapshotMode);
83
maGroupList[i]->setUpdateInterval(mUpdateInterval);
84
maGroupList[i]->setGameAnimEnabled(mGameAnimEnabled);
85
maGroupList[i]->setWaitForAllUpdate(mWaitForAllUpdate);
86
addItem(maGroupList[i]);
88
maGameScoreList[i] = new KBlocksScore();
89
maGameScoreList[i]->setLevelUpFactor(KBlocksScore_Level_x_Level_x_Factor, 1000);
90
maGameScoreList[i]->setScoreUpFactor(10);
92
maGameReadySignal[i] = false;
93
connect(maGroupList[i], SIGNAL(readyForAction(int)), this, SLOT(readyForAction(int)));
98
//Our Message Item, hidden by default
99
mMessageBox = new KGamePopupItem();
100
mMessageBox->setMessageOpacity(0.9);
101
addItem(mMessageBox);
104
void KBlocksScene::deleteGameItemGroups()
106
removeItem(mMessageBox);
109
for(int i = 0; i < mGroupCount; i++)
111
disconnect(maGroupList[i], SIGNAL(readyForAction(int)), this, SLOT(readyForAction(int)));
113
delete maGameScoreList[i];
114
maGameScoreList[i] = 0;
116
removeItem(maGroupList[i]);
117
delete maGroupList[i];
123
void KBlocksScene::setGamesPerLine(int count)
125
mSceneGamesPerLine = count;
128
void KBlocksScene::setGameAnimEnabled(bool flag)
130
mGameAnimEnabled = flag;
131
for(int i = 0; i < mGroupCount; i++)
133
maGroupList[i]->setGameAnimEnabled(flag);
137
void KBlocksScene::setWaitForAllUpdate(bool flag)
139
mWaitForAllUpdate = flag;
140
for(int i = 0; i < mGroupCount; i++)
142
maGroupList[i]->setWaitForAllUpdate(flag);
146
void KBlocksScene::setUpdateInterval(int interval)
148
mUpdateInterval = interval;
149
mUpdateTimer.setInterval(mUpdateInterval);
150
for(int i = 0; i < mGroupCount; i++)
152
maGroupList[i]->setUpdateInterval(mUpdateInterval);
156
void KBlocksScene::setSoundsEnabled(bool enabled)
158
mpSnd->setSoundsEnabled(enabled);
161
void KBlocksScene::readSettings(const QSize & viewSize)
163
if (mpGrafx->theme()->fileName()!=Settings::theme())
165
mpGrafx->loadTheme(Settings::theme());
166
mpSnd->loadTheme(Settings::theme());
167
mpGrafx->adjustForSize(viewSize);
172
void KBlocksScene::viewScaled(const QSize& /*newsize*/)
175
//Temporarily halt game timer while resizing elements
176
if (gameState==Game_Active) stepTimer.stop();
177
grafx->adjustForSize(newsize);
179
//Do not restart if game was paused
180
if (gameState==Game_Active) stepTimer.start();
184
void KBlocksScene::startGame()
187
for(int i = 0; i < mGroupCount; i++)
189
maGroupList[i]->startGame();
194
mUpdateTimer.start();
195
QTimer::singleShot(500, this, SLOT(greetPlayer()));
199
void KBlocksScene::stopGame()
201
for(int i = 0; i < mGroupCount; i++)
203
maGroupList[i]->stopGame();
209
void KBlocksScene::pauseGame(bool flag, bool fromUI)
211
QString resuming(i18n("Game Resumed!"));
212
QString pausing(i18n("Game Paused!"));
214
for(int i = 0; i < mGroupCount; i++)
216
maGroupList[i]->pauseGame(flag);
226
showMessage(pausing, 2000);
231
mUpdateTimer.start();
234
showMessage(resuming, 2000);
240
void KBlocksScene::addScore(int gameIndex, int lineCount)
246
maGameScoreList[gameIndex]->addScore(lineCount);
247
emit scoreChanged(gameIndex, maGameScoreList[gameIndex]->getScorePoint(),
248
maGameScoreList[gameIndex]->getLineCount(),
249
maGameScoreList[gameIndex]->getGameLevel());
252
void KBlocksScene::updateDimensions()
254
// TODO : Reset item position and scale
255
int width = (mGroupCount >= mSceneGamesPerLine) ? mSceneGamesPerLine : (mGroupCount % mSceneGamesPerLine);
256
int height = (int)(mGroupCount / (mSceneGamesPerLine + 1)) + 1;
258
setSceneRect(0, 0, mpGrafx->m_View_Size_Width * width,
259
mpGrafx->m_View_Size_Height * height);
261
for(int i = 0; i < mGroupCount; i++)
263
int left = mpGrafx->m_View_Size_Width * (i % mSceneGamesPerLine);
264
int top = mpGrafx->m_View_Size_Height * ((int)(i / mSceneGamesPerLine));
266
maGroupList[i]->setPos(left, top);
267
maGroupList[i]->refreshPosition();
271
void KBlocksScene::greetPlayer()
273
QString greets(i18n("Game Start!"));
274
showMessage( greets, 2000 );
277
void KBlocksScene::gameOverPlayer()
279
QString greets(i18n("Game Over!"));
280
showMessage( greets, 2000 );
283
void KBlocksScene::gameOverMultiWin()
285
QString gameOver(i18n("You Win!"));
286
showMessage( gameOver, 2000 );
289
void KBlocksScene::gameOverMultiLose()
291
QString gameOver(i18n("You Lose!"));
292
showMessage( gameOver, 2000 );
295
void KBlocksScene::showMessage(const QString& message, int ms)
297
mMessageBox->setMessageTimeout( ms );
298
mMessageBox->showMessage( message, KGamePopupItem::TopLeft );
301
void KBlocksScene::updateGame()
308
QVarLengthArray<int, 16> removedLines(mGroupCount);
309
int gameCount = mpGameLogic->updateGame(removedLines.data());
311
for(int i = 0; i < mGroupCount; i++)
313
if (removedLines[i] > 0)
315
if (maGameScoreList[i]->addScore(removedLines[i]))
317
int tmpLevel = maGameScoreList[i]->getGameLevel();
318
if (mTopGameLevel < tmpLevel)
320
mpGameLogic->levelUpGame(tmpLevel - mTopGameLevel);
321
mTopGameLevel = tmpLevel;
324
emit scoreChanged(i, maGameScoreList[i]->getScorePoint(),
325
maGameScoreList[i]->getLineCount(),
326
maGameScoreList[i]->getGameLevel());
328
else if (removedLines[i] == -1)
330
maGroupList[i]->stopGame();
331
if (mGroupCount == 1)
333
QTimer::singleShot(500, this, SLOT(gameOverPlayer()));
334
emit isHighscore(0, maGameScoreList[0]->getScorePoint(),
335
maGameScoreList[0]->getGameLevel());
341
for (int j = 0; j < mGroupCount; j++)
343
maGroupList[j]->stopGame();
345
QTimer::singleShot(500, this, SLOT(gameOverMultiLose()));
346
emit isHighscore(0, maGameScoreList[0]->getScorePoint(),
347
maGameScoreList[0]->getGameLevel());
349
else if (gameCount <= 1)
351
maGroupList[0]->stopGame();
352
QTimer::singleShot(500, this, SLOT(gameOverMultiWin()));
353
emit isHighscore(0, maGameScoreList[0]->getScorePoint(),
354
maGameScoreList[0]->getGameLevel());
361
void KBlocksScene::readyForAction(int groupID)
363
maGameReadySignal[groupID] = true;
364
bool allReady = true;
365
for(int i = 0; i < mGroupCount; i++)
367
if (!maGameReadySignal[i])
374
for(int i = 0; i < mGroupCount; i++)
376
if (mpGameLogic->getSingleGame(i)->isGameRunning())
378
maGameReadySignal[i] = false;
381
mpGameLogic->continueGame();
385
void KBlocksScene::drawBackground( QPainter * painter, const QRectF & rect )
387
if (mpGrafx->renderer()->isValid())
389
mpGrafx->renderer()->render(painter, QString("BACKGROUND"), rect);