File indexing completed on 2024-04-21 04:02:09
0001 /****************************************************************************** 0002 * KBlocks, a falling blocks game by KDE * 0003 * SPDX-FileCopyrightText: 2009-2021 Mauricio Piacentini <mauricio@tabuleiro.com> * 0004 * Zhongjie Cai <squall.leonhart.cai@gmail.com> * 0005 * Julian Helfferich <julian.helfferich@mailbox.org> * 0006 * * 0007 * SPDX-License-Identifier: GPL-2.0-or-later 0008 ******************************************************************************/ 0009 #include "KBlocksWin.h" 0010 0011 #include <limits.h> 0012 // KDEGames 0013 #include <KGameThemeSelector> 0014 #include <KGameThemeProvider> 0015 #include <KGameDifficulty> 0016 #include <KGameHighScoreDialog> 0017 #include <KGameStandardAction> 0018 // KF 0019 #include <KToggleAction> 0020 #include <KStandardAction> 0021 #include <KActionCollection> 0022 #include <KLocalizedString> 0023 // Qt 0024 #include <QStatusBar> 0025 #include <QPixmapCache> 0026 #include <QPointer> 0027 #include <QLabel> 0028 #include <QRandomGenerator> 0029 0030 #include "GameLogicInterface.h" 0031 #include "KBlocksScene.h" 0032 #include "SceneInterface.h" 0033 #include "settings.h" 0034 0035 KBlocksWin::KBlocksWin( 0036 GameLogicInterface *p, 0037 GraphicsInterface *graphics, 0038 SoundInterface *sound, 0039 KGameThemeProvider *themeProvider, 0040 KBlocksPlayManager *pM, 0041 int capacity, 0042 int gamecount 0043 ) : KXmlGuiWindow() 0044 { 0045 if (themeProvider) { 0046 m_themeSelector = new KGameThemeSelector(themeProvider, KGameThemeSelector::EnableNewStuffDownload); 0047 connect(themeProvider, &KGameThemeProvider::currentThemeChanged, this, &KBlocksWin::onThemeChanged); 0048 } 0049 0050 //Use up to 3MB for global application pixmap cache 0051 QPixmapCache::setCacheLimit(3 * 1024); 0052 0053 mpKBPlayer = new KBlocksKeyboardPlayer(this); 0054 mpAIPlayer = new KBlocksAIPlayer(); 0055 0056 mMaxGameCapacity = capacity; 0057 mGameCount = gamecount; 0058 mpGameLogic = p; 0059 connect(mpGameLogic, &GameLogicInterface::allGamesStopped, 0060 this, &KBlocksWin::onAllGamesStopped); 0061 0062 mpPlayManager = pM; 0063 0064 mpGameScene = new KBlocksScene(mpGameLogic, graphics, sound, capacity); 0065 0066 connect(mpKBPlayer, &KBlocksKeyboardPlayer::blockMoved, 0067 mpGameScene, &SceneInterface::playMoveSound); 0068 connect(mpKBPlayer, &KBlocksKeyboardPlayer::blockDropped, 0069 mpGameScene, &SceneInterface::playDropSound); 0070 0071 mpGameView = new KBlocksView(mpGameScene, this); 0072 mpGameView->show(); 0073 setCentralWidget(mpGameView); 0074 connect(mpGameView, &KBlocksView::focusEvent, this, &KBlocksWin::focusEvent); 0075 0076 setAutoSaveSettings(); 0077 } 0078 0079 KBlocksWin::~KBlocksWin() 0080 { 0081 delete m_themeSelector; 0082 delete mpGameView; 0083 delete mpGameScene; 0084 delete mpAIPlayer; 0085 delete mpKBPlayer; 0086 } 0087 0088 void KBlocksWin::setGamesPerLine(int count) 0089 { 0090 mpGameScene->setGamesPerLine(count); 0091 } 0092 0093 void KBlocksWin::setGameAnimEnabled(bool flag) 0094 { 0095 mpGameScene->setGameAnimEnabled(flag); 0096 mGameAnim = flag; 0097 } 0098 0099 void KBlocksWin::setWaitForAllUpdate(bool flag) 0100 { 0101 mpGameScene->setWaitForAllUpdate(flag); 0102 mWaitForAll = flag; 0103 } 0104 0105 void KBlocksWin::setUpdateInterval(int interval) 0106 { 0107 mpGameScene->setUpdateInterval(interval); 0108 } 0109 0110 void KBlocksWin::addScore(int gameIndex, int lineCount) 0111 { 0112 mpGameScene->addScore(gameIndex, lineCount); 0113 } 0114 0115 void KBlocksWin::startGame() 0116 { 0117 mpGameLogic->setGameSeed(QRandomGenerator::global()->generate()); 0118 if (mpGameLogic->startGame(mGameCount)) { 0119 mpPlayManager->startGame(); 0120 0121 mpGameScene->createGameItemGroups(mGameCount, false); 0122 mpGameScene->startGame(); 0123 0124 int levelUpTime = 0; 0125 switch ((int) KGameDifficulty::globalLevel()) { 0126 case KGameDifficultyLevel::Medium: 0127 levelUpTime = 5; 0128 break; 0129 case KGameDifficultyLevel::Hard: 0130 levelUpTime = 10; 0131 break; 0132 } 0133 mpGameLogic->levelUpGame(levelUpTime); 0134 0135 KGameDifficulty::global()->setGameRunning(true); 0136 } else { 0137 stopGame(); 0138 startGame(); 0139 } 0140 0141 mpGameView->fitInView(mpGameScene->sceneRect(), Qt::KeepAspectRatio); 0142 0143 mScore->setText(i18n("Points: %1 - Lines: %2 - Level: %3", 0, 0, 0)); 0144 0145 m_pauseAction->setEnabled(true); 0146 m_pauseAction->setChecked(false); 0147 } 0148 0149 void KBlocksWin::stopGame() 0150 { 0151 if (mpGameLogic->hasSingleGames()) { 0152 mpGameScene->stopGame(); 0153 mpGameLogic->deleteSingleGames(); 0154 // Clear the game field 0155 mpGameScene->deleteGameItemGroups(); 0156 } 0157 } 0158 0159 void KBlocksWin::pauseGame() 0160 { 0161 mpGameLogic->pauseGame(m_pauseAction->isChecked()); 0162 mpPlayManager->pauseGame(m_pauseAction->isChecked()); 0163 mpGameScene->pauseGame(m_pauseAction->isChecked()); 0164 0165 mpKBPlayer->pauseGame(m_pauseAction->isChecked()); 0166 mpAIPlayer->pauseGame(m_pauseAction->isChecked()); 0167 0168 KGameDifficulty::global()->setGameRunning(!m_pauseAction->isChecked()); 0169 } 0170 0171 void KBlocksWin::onAllGamesStopped() 0172 { 0173 mpPlayManager->stopGame(); 0174 m_pauseAction->setEnabled(false); 0175 KGameDifficulty::global()->setGameRunning(false); 0176 } 0177 0178 void KBlocksWin::singleGame() 0179 { 0180 mpPlayManager->stopGame(); 0181 mpPlayManager->clearGamePlayer(); 0182 mpPlayManager->addGamePlayer(mpKBPlayer, -1, -1); 0183 mGameCount = 1; 0184 0185 startGame(); 0186 } 0187 0188 void KBlocksWin::pveStepGame() 0189 { 0190 mpPlayManager->stopGame(); 0191 mpPlayManager->clearGamePlayer(); 0192 mpPlayManager->addGamePlayer(mpKBPlayer, -1, -1); 0193 mpPlayManager->addGamePlayer(mpAIPlayer, 200, 50); 0194 mGameCount = 2; 0195 0196 mpGameLogic->setGameStandbyMode(true); 0197 setWaitForAllUpdate(true); 0198 0199 startGame(); 0200 } 0201 0202 void KBlocksWin::focusEvent(bool flag) 0203 { 0204 if (!flag) { 0205 if (m_pauseAction->isChecked()) { 0206 return; 0207 } 0208 } 0209 mpGameLogic->pauseGame(flag); 0210 mpPlayManager->pauseGame(flag); 0211 mpGameScene->pauseGame(flag, true); 0212 } 0213 0214 void KBlocksWin::closeEvent(QCloseEvent *event) 0215 { 0216 Settings::self()->save(); 0217 KXmlGuiWindow::closeEvent(event); 0218 } 0219 0220 void KBlocksWin::showHighscore() 0221 { 0222 KGameHighScoreDialog ksdialog(KGameHighScoreDialog::Name | KGameHighScoreDialog::Level | KGameHighScoreDialog::Score, this); 0223 ksdialog.initFromDifficulty(KGameDifficulty::global()); 0224 ksdialog.exec(); 0225 } 0226 0227 void KBlocksWin::configureSettings() 0228 { 0229 m_themeSelector->showAsDialog(); 0230 } 0231 0232 void KBlocksWin::onThemeChanged(const KGameTheme *theme) 0233 { 0234 // sync to settings store 0235 Settings::setTheme(QString::fromUtf8(theme->identifier())); 0236 // trigger update of resources, then display 0237 mpGameView->loadTheme(theme); 0238 } 0239 0240 void KBlocksWin::onScoreChanged(int index, int points, int lines, int level) 0241 { 0242 if (index == 0) { // TODO : game id?? multi game display?? 0243 mScore->setText(i18n("Points: %1 - Lines: %2 - Level: %3", points, lines, level)); 0244 } 0245 } 0246 0247 void KBlocksWin::onIsHighscore(int index, int points, int level) 0248 { 0249 if (index == 0) { // TODO : game id?? multi game display?? 0250 QPointer<KGameHighScoreDialog> ksdialog = new KGameHighScoreDialog(KGameHighScoreDialog::Name | KGameHighScoreDialog::Level | KGameHighScoreDialog::Score, this); 0251 ksdialog->initFromDifficulty(KGameDifficulty::global()); 0252 KGameHighScoreDialog::FieldInfo info; 0253 info[KGameHighScoreDialog::Score].setNum(points); 0254 info[KGameHighScoreDialog::Level].setNum(level); 0255 if (ksdialog->addScore(info)) { 0256 ksdialog->exec(); 0257 } 0258 delete ksdialog; 0259 } 0260 } 0261 0262 void KBlocksWin::levelChanged() 0263 { 0264 //Scene reads the difficulty level for us 0265 if (mGameCount == 1) { 0266 singleGame(); 0267 } else { 0268 pveStepGame(); 0269 } 0270 mpGameView->setFocus(Qt::MouseFocusReason); 0271 } 0272 0273 void KBlocksWin::setSoundsEnabled(bool enabled) 0274 { 0275 mpGameScene->setSoundsEnabled(enabled); 0276 Settings::setSounds(enabled); 0277 } 0278 0279 void KBlocksWin::setupGUILayout() 0280 { 0281 QAction *action; 0282 0283 action = KGameStandardAction::gameNew(this, &KBlocksWin::singleGame, actionCollection()); 0284 action->setText(i18n("Single Game")); 0285 actionCollection()->addAction(QStringLiteral("newGame"), action); 0286 0287 action = new QAction(this); 0288 action->setText(i18n("Human vs AI")); 0289 actionCollection()->addAction(QStringLiteral("pve_step"), action); 0290 connect(action, &QAction::triggered, this, &KBlocksWin::pveStepGame); 0291 0292 m_pauseAction = KGameStandardAction::pause(this, &KBlocksWin::pauseGame, actionCollection()); 0293 actionCollection()->addAction(QStringLiteral("pauseGame"), m_pauseAction); 0294 m_pauseAction->setEnabled(false); 0295 0296 action = KGameStandardAction::highscores(this, &KBlocksWin::showHighscore, actionCollection()); 0297 actionCollection()->addAction(QStringLiteral("showHighscores"), action); 0298 0299 action = KGameStandardAction::quit(this, &KBlocksWin::close, actionCollection()); 0300 actionCollection()->addAction(QStringLiteral("quit"), action); 0301 0302 if (m_themeSelector) { 0303 KStandardAction::preferences(this, &KBlocksWin::configureSettings, actionCollection()); 0304 } 0305 0306 KToggleAction *soundAction = new KToggleAction(i18n("&Play Sounds"), this); 0307 soundAction->setChecked(Settings::sounds()); 0308 actionCollection()->addAction(QStringLiteral("sounds"), soundAction); 0309 connect(soundAction, &KToggleAction::triggered, this, &KBlocksWin::setSoundsEnabled); 0310 mpGameScene->setSoundsEnabled(Settings::sounds()); 0311 0312 // TODO 0313 mScore = new QLabel(i18n("Points: 0 - Lines: 0 - Level: 0")); 0314 statusBar()->addPermanentWidget(mScore); 0315 connect(mpGameScene, &KBlocksScene::scoreChanged, this, &KBlocksWin::onScoreChanged); 0316 connect(mpGameScene, &KBlocksScene::isHighscore, this, &KBlocksWin::onIsHighscore); 0317 0318 KGameDifficulty::global()->addStandardLevelRange( 0319 KGameDifficultyLevel::Easy, KGameDifficultyLevel::Hard 0320 ); 0321 KGameDifficultyGUI::init(this); 0322 connect(KGameDifficulty::global(), &KGameDifficulty::currentLevelChanged, this, &KBlocksWin::levelChanged); 0323 0324 setupGUI(); 0325 } 0326 0327 #include "moc_KBlocksWin.cpp"