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)
22
mSnapshotMode = false;
25
mMaxCapacity = capacity;
26
mSceneGamesPerLine = 4;
27
mGameAnimEnabled = true;
28
mWaitForAllUpdate = false;
30
maGroupList = new KBlocksItemGroup*[capacity]();
31
maGameScoreList = new KBlocksScore*[capacity]();
32
maGameReadySignal = new bool[capacity]();
34
QString themeFile(Settings::theme());
35
mpGrafx = new KBlocksGraphics(themeFile);
36
mpSnd = new KBlocksSound(themeFile);
38
int width = (capacity >= mSceneGamesPerLine) ? mSceneGamesPerLine : (capacity % mSceneGamesPerLine);
39
int height = (int)(capacity / (mSceneGamesPerLine + 1)) + 1;
40
setSceneRect(0, 0, mpGrafx->m_View_Size_Width * width,
41
mpGrafx->m_View_Size_Height * height);
43
setItemIndexMethod(NoIndex);
46
mUpdateTimer.setInterval(mUpdateInterval);
47
connect(&mUpdateTimer, SIGNAL(timeout()), SLOT(updateGame()));
51
KBlocksScene::~KBlocksScene()
53
delete [] maGameReadySignal;
54
delete [] maGameScoreList;
55
delete [] maGroupList;
61
KBlocksItemGroup* KBlocksScene::getItemGroup(int index)
63
return maGroupList[index];
66
KBlocksScore* KBlocksScene::getScoreHandler(int index)
68
return maGameScoreList[index];
71
void KBlocksScene::createGameItemGroups(int groupCount, bool snapshotMode)
73
if (groupCount > mMaxCapacity)
75
mGroupCount = mMaxCapacity;
77
mGroupCount = groupCount;
78
mSnapshotMode = snapshotMode;
81
for(int i = 0; i < mGroupCount; i++)
83
maGroupList[i] = new KBlocksItemGroup(i, mpGameLogic->getSingleGame(i), mpGrafx, mpSnd, snapshotMode);
84
maGroupList[i]->setUpdateInterval(mUpdateInterval);
85
maGroupList[i]->setGameAnimEnabled(mGameAnimEnabled);
86
maGroupList[i]->setWaitForAllUpdate(mWaitForAllUpdate);
87
addItem(maGroupList[i]);
89
maGameScoreList[i] = new KBlocksScore();
90
maGameScoreList[i]->setLevelUpFactor(KBlocksScore_Level_x_Level_x_Factor, 1000);
91
maGameScoreList[i]->setScoreUpFactor(10);
93
maGameReadySignal[i] = false;
94
connect(maGroupList[i], SIGNAL(readyForAction(int)), this, SLOT(readyForAction(int)));
99
//Our Message Item, hidden by default
100
mMessageBox = new KGamePopupItem();
101
mMessageBox->setMessageOpacity(0.9);
102
addItem(mMessageBox);
105
void KBlocksScene::deleteGameItemGroups()
107
removeItem(mMessageBox);
110
for(int i = 0; i < mGroupCount; i++)
112
disconnect(maGroupList[i], SIGNAL(readyForAction(int)), this, SLOT(readyForAction(int)));
114
delete maGameScoreList[i];
115
maGameScoreList[i] = 0;
117
removeItem(maGroupList[i]);
118
delete maGroupList[i];
124
void KBlocksScene::setGamesPerLine(int count)
126
mSceneGamesPerLine = count;
129
void KBlocksScene::setGameAnimEnabled(bool flag)
131
mGameAnimEnabled = flag;
132
for(int i = 0; i < mGroupCount; i++)
134
maGroupList[i]->setGameAnimEnabled(flag);
138
void KBlocksScene::setWaitForAllUpdate(bool flag)
140
mWaitForAllUpdate = flag;
141
for(int i = 0; i < mGroupCount; i++)
143
maGroupList[i]->setWaitForAllUpdate(flag);
147
void KBlocksScene::setUpdateInterval(int interval)
149
mUpdateInterval = interval;
150
mUpdateTimer.setInterval(mUpdateInterval);
151
for(int i = 0; i < mGroupCount; i++)
153
maGroupList[i]->setUpdateInterval(mUpdateInterval);
157
void KBlocksScene::setSoundsEnabled(bool enabled)
159
mpSnd->setSoundsEnabled(enabled);
162
void KBlocksScene::readSettings(const QSize & viewSize)
164
if (mpGrafx->theme()->fileName()!=Settings::theme())
166
mpGrafx->loadTheme(Settings::theme());
167
mpSnd->loadTheme(Settings::theme());
168
mpGrafx->adjustForSize(viewSize);
173
void KBlocksScene::viewScaled(const QSize& /*newsize*/)
176
//Temporarily halt game timer while resizing elements
177
if (gameState==Game_Active) stepTimer.stop();
178
grafx->adjustForSize(newsize);
180
//Do not restart if game was paused
181
if (gameState==Game_Active) stepTimer.start();
185
void KBlocksScene::startGame()
194
for(int i = 0; i < mGroupCount; i++)
196
maGroupList[i]->startGame();
201
mUpdateTimer.start();
202
QTimer::singleShot(500, this, SLOT(greetPlayer()));
206
void KBlocksScene::stopGame()
212
mGameStarted = false;
214
for(int i = 0; i < mGroupCount; i++)
216
maGroupList[i]->stopGame();
222
void KBlocksScene::pauseGame(bool flag, bool fromUI)
229
QString resuming(i18n("Game Resumed!"));
230
QString pausing(i18n("Game Paused!"));
232
for(int i = 0; i < mGroupCount; i++)
234
maGroupList[i]->pauseGame(flag);
244
showMessage(pausing, 2000);
249
mUpdateTimer.start();
252
showMessage(resuming, 2000);
258
void KBlocksScene::addScore(int gameIndex, int lineCount)
264
maGameScoreList[gameIndex]->addScore(lineCount);
265
emit scoreChanged(gameIndex, maGameScoreList[gameIndex]->getScorePoint(),
266
maGameScoreList[gameIndex]->getLineCount(),
267
maGameScoreList[gameIndex]->getGameLevel());
270
void KBlocksScene::updateDimensions()
272
// TODO : Reset item position and scale
273
int width = (mGroupCount >= mSceneGamesPerLine) ? mSceneGamesPerLine : (mGroupCount % mSceneGamesPerLine);
274
int height = (int)(mGroupCount / (mSceneGamesPerLine + 1)) + 1;
276
setSceneRect(0, 0, mpGrafx->m_View_Size_Width * width,
277
mpGrafx->m_View_Size_Height * height);
279
for(int i = 0; i < mGroupCount; i++)
281
int left = mpGrafx->m_View_Size_Width * (i % mSceneGamesPerLine);
282
int top = mpGrafx->m_View_Size_Height * ((int)(i / mSceneGamesPerLine));
284
maGroupList[i]->setPos(left, top);
285
maGroupList[i]->refreshPosition();
289
void KBlocksScene::greetPlayer()
291
QString greets(i18n("Game Start!"));
292
showMessage( greets, 2000 );
295
void KBlocksScene::gameOverPlayer()
297
QString greets(i18n("Game Over!"));
298
showMessage( greets, 2000 );
301
void KBlocksScene::gameOverMultiWin()
303
QString gameOver(i18n("You Win!"));
304
showMessage( gameOver, 2000 );
307
void KBlocksScene::gameOverMultiLose()
309
QString gameOver(i18n("You Lose!"));
310
showMessage( gameOver, 2000 );
313
void KBlocksScene::showMessage(const QString& message, int ms)
315
mMessageBox->setMessageTimeout( ms );
316
mMessageBox->showMessage( message, KGamePopupItem::TopLeft );
319
void KBlocksScene::updateGame()
326
QVarLengthArray<int, 16> removedLines(mGroupCount);
327
int gameCount = mpGameLogic->updateGame(removedLines.data());
329
for(int i = 0; i < mGroupCount; i++)
331
if (removedLines[i] > 0)
333
if (maGameScoreList[i]->addScore(removedLines[i]))
335
int tmpLevel = maGameScoreList[i]->getGameLevel();
336
if (mTopGameLevel < tmpLevel)
338
mpGameLogic->levelUpGame(tmpLevel - mTopGameLevel);
339
mTopGameLevel = tmpLevel;
342
emit scoreChanged(i, maGameScoreList[i]->getScorePoint(),
343
maGameScoreList[i]->getLineCount(),
344
maGameScoreList[i]->getGameLevel());
346
else if (removedLines[i] == -1)
348
maGroupList[i]->stopGame();
349
if (mGroupCount == 1)
351
QTimer::singleShot(500, this, SLOT(gameOverPlayer()));
352
emit isHighscore(0, maGameScoreList[0]->getScorePoint(),
353
maGameScoreList[0]->getGameLevel());
359
for (int j = 0; j < mGroupCount; j++)
361
maGroupList[j]->stopGame();
363
QTimer::singleShot(500, this, SLOT(gameOverMultiLose()));
364
emit isHighscore(0, maGameScoreList[0]->getScorePoint(),
365
maGameScoreList[0]->getGameLevel());
367
else if (gameCount <= 1)
369
maGroupList[0]->stopGame();
370
QTimer::singleShot(500, this, SLOT(gameOverMultiWin()));
371
emit isHighscore(0, maGameScoreList[0]->getScorePoint(),
372
maGameScoreList[0]->getGameLevel());
379
void KBlocksScene::readyForAction(int groupID)
381
maGameReadySignal[groupID] = true;
382
bool allReady = true;
383
for(int i = 0; i < mGroupCount; i++)
385
if (!maGameReadySignal[i])
392
for(int i = 0; i < mGroupCount; i++)
394
if (mpGameLogic->getSingleGame(i)->isGameRunning())
396
maGameReadySignal[i] = false;
399
mpGameLogic->continueGame();
403
void KBlocksScene::drawBackground( QPainter * painter, const QRectF & rect )
405
if (mpGrafx->renderer()->isValid())
407
mpGrafx->renderer()->render(painter, QString("BACKGROUND"), rect);