File indexing completed on 2024-04-28 04:04:38
0001 /* 0002 This file is part of the game 'KTron' 0003 0004 SPDX-FileCopyrightText: 1998-2000 Matthias Kiefer <matthias.kiefer@gmx.de> 0005 SPDX-FileCopyrightText: 2005 Benjamin C. Meyer <ben at meyerhome dot net> 0006 SPDX-FileCopyrightText: 2008-2009 Stas Verberkt <legolas at legolasweb dot nl> 0007 0008 SPDX-License-Identifier: GPL-2.0-or-later 0009 0010 */ 0011 0012 #include "ktron.h" 0013 #include "renderer.h" 0014 #include "settings.h" 0015 #include "ui_general.h" 0016 0017 #include <KGameDifficulty> 0018 #include <KGameHighScoreDialog> 0019 #include <KGameStandardAction> 0020 #include <KGameThemeSelector> 0021 0022 #include <QApplication> 0023 #include <QStatusBar> 0024 0025 #include <KActionCollection> 0026 #include <KConfigDialog> 0027 #include <KLocalizedString> 0028 #include <KMessageBox> 0029 #include <KShortcutsDialog> 0030 0031 //UI 0032 class General : public QWidget, public Ui::General 0033 { 0034 public: 0035 explicit General(QWidget *parent = nullptr) 0036 : QWidget(parent) 0037 { 0038 setupUi(this); 0039 } 0040 }; 0041 0042 /** 0043 * Constructor 0044 */ 0045 KTron::KTron(QWidget *parent) : KXmlGuiWindow(parent, Qt::WindowFlags()) { 0046 m_tron = new Tron(this); 0047 connect(m_tron, &Tron::gameEnds, this, &KTron::changeStatus); 0048 connect(m_tron, &Tron::updatedScore, this, &KTron::updateScore); 0049 connect(m_tron, &Tron::pauseBlocked, this, &KTron::blockPause); 0050 m_tron->setMinimumSize(700,420); 0051 setCentralWidget(m_tron); 0052 0053 // create statusbar 0054 for (auto &label : m_statusBarLabel) { 0055 label = new QLabel(this); 0056 label->setAlignment(Qt::AlignCenter); 0057 statusBar()->addWidget(label, 1); 0058 } 0059 0060 // We match up keyboard events ourselves in Tron::keyPressEvent() 0061 // We must disable the actions, otherwise we don't get the keyPressEvent's 0062 0063 m_player0Up = actionCollection()->addAction( QStringLiteral( "Pl1Up" )); 0064 m_player0Up->setText(i18n("Right Player / KSnake mode: Up")); 0065 KActionCollection::setDefaultShortcut(m_player0Up, Qt::Key_Up); 0066 connect(m_player0Up, &QAction::triggered, this, &KTron::triggerKey0Up); 0067 addAction(m_player0Up); 0068 0069 m_player0Down = actionCollection()->addAction( QStringLiteral( "Pl1Down" )); 0070 m_player0Down->setText(i18n("Right Player / KSnake mode: Down")); 0071 KActionCollection::setDefaultShortcut(m_player0Down, Qt::Key_Down); 0072 connect(m_player0Down, &QAction::triggered, this, &KTron::triggerKey0Down); 0073 addAction(m_player0Down); 0074 0075 m_player0Right = actionCollection()->addAction( QStringLiteral( "Pl1Right" )); 0076 m_player0Right->setText(i18n("Right Player / KSnake mode: Right")); 0077 KActionCollection::setDefaultShortcut(m_player0Right, Qt::Key_Right); 0078 connect(m_player0Right, &QAction::triggered, this, &KTron::triggerKey0Right); 0079 addAction(m_player0Right); 0080 0081 m_player0Left = actionCollection()->addAction( QStringLiteral( "Pl1Left" )); 0082 m_player0Left->setText(i18n("Right Player / KSnake mode: Left")); 0083 KActionCollection::setDefaultShortcut(m_player0Left, Qt::Key_Left); 0084 connect(m_player0Left, &QAction::triggered, this, &KTron::triggerKey0Left); 0085 addAction(m_player0Left); 0086 0087 m_player0Accelerate = actionCollection()->addAction( QStringLiteral( "Pl1Ac" )); 0088 m_player0Accelerate->setText(i18n("Right Player: Accelerator")); 0089 KActionCollection::setDefaultShortcut(m_player0Accelerate, Qt::Key_0); 0090 m_player0Accelerate->setEnabled(false); // Alternate handling, because of up/down events 0091 addAction(m_player0Accelerate); 0092 0093 m_player1Up = actionCollection()->addAction( QStringLiteral( "Pl2Up" )); 0094 m_player1Up->setText(i18n("Left Player: Up")); 0095 KActionCollection::setDefaultShortcut(m_player1Up, Qt::Key_W); 0096 connect(m_player1Up, &QAction::triggered, this, &KTron::triggerKey1Up); 0097 addAction(m_player1Up); 0098 0099 m_player1Down = actionCollection()->addAction( QStringLiteral( "Pl2Down" )); 0100 m_player1Down->setText(i18n("Left Player: Down")); 0101 KActionCollection::setDefaultShortcut(m_player1Down, Qt::Key_S); 0102 connect(m_player1Down, &QAction::triggered, this, &KTron::triggerKey1Down); 0103 addAction(m_player1Down); 0104 0105 m_player1Right = actionCollection()->addAction( QStringLiteral( "Pl2Right" ));; 0106 m_player1Right->setText(i18n("Left Player: Right")); 0107 KActionCollection::setDefaultShortcut(m_player1Right, Qt::Key_D); 0108 connect(m_player1Right, &QAction::triggered, this, &KTron::triggerKey1Right); 0109 addAction(m_player1Right); 0110 0111 m_player1Left = actionCollection()->addAction( QStringLiteral( "Pl2Left" )); 0112 m_player1Left->setText(i18n("Left Player: Left")); 0113 KActionCollection::setDefaultShortcut(m_player1Left, Qt::Key_A); 0114 connect(m_player1Left, &QAction::triggered, this, &KTron::triggerKey1Left); 0115 addAction(m_player1Left); 0116 0117 m_player1Accelerate = actionCollection()->addAction( QStringLiteral( "Pl2Ac" )); 0118 m_player1Accelerate->setText(i18n("Left Player: Accelerator")); 0119 KActionCollection::setDefaultShortcut(m_player1Accelerate, Qt::Key_Q); 0120 m_player1Accelerate->setEnabled(false); // Alternate handling, because of up/down events 0121 addAction(m_player1Accelerate); 0122 0123 // Pause 0124 m_pauseButton = KGameStandardAction::pause(m_tron, &Tron::togglePause, actionCollection()); 0125 m_pauseButton->setEnabled(false); 0126 // New 0127 KGameStandardAction::gameNew(m_tron, &Tron::newGame, actionCollection()); 0128 // Quit 0129 KGameStandardAction::quit(qApp, &QApplication::quit, actionCollection()); 0130 // Settings 0131 KStandardAction::preferences(this, &KTron::showSettings, actionCollection()); 0132 // Configure keys 0133 KStandardAction::keyBindings(this, &KTron::optionsConfigureKeys, actionCollection()); 0134 // Highscores 0135 KGameStandardAction::highscores(this, &KTron::showHighscores, actionCollection()); 0136 0137 //difficulty 0138 KGameDifficulty::global()->addStandardLevelRange( 0139 KGameDifficultyLevel::VeryEasy, KGameDifficultyLevel::VeryHard, 0140 KGameDifficultyLevel::Easy //default 0141 ); 0142 KGameDifficultyGUI::init(this); 0143 connect(KGameDifficulty::global(), &KGameDifficulty::currentLevelChanged, m_tron, &Tron::loadSettings); 0144 connect(Renderer::self()->themeProvider(), &KGameThemeProvider::currentThemeChanged, 0145 [this](const KGameTheme *theme) { 0146 Settings::setTheme(QString::fromUtf8(theme->identifier())); 0147 }); 0148 0149 setupGUI( KXmlGuiWindow::Keys | StatusBar | Save | Create); 0150 loadSettings(); 0151 m_tron->loadSettings(); 0152 } 0153 0154 KTron::~KTron() 0155 { 0156 delete m_tron; 0157 } 0158 0159 void KTron::loadSettings() { 0160 if (!Renderer::self()->loadTheme(Settings::theme())) 0161 { 0162 KMessageBox::error(this, i18n("Failed to load \"%1\" theme. Please check your installation.", Settings::theme())); 0163 } 0164 0165 m_tron->getPlayer(0)->setName(Settings::namePlayer1()); 0166 m_tron->getPlayer(1)->setName(Settings::namePlayer2()); 0167 Settings::setNamePlayer1(m_tron->getPlayer(0)->getName()); 0168 if (!m_tron->getPlayer(1)->isComputer()) { 0169 Settings::setNamePlayer2(m_tron->getPlayer(1)->getName()); 0170 } 0171 0172 updateStatusbar(); 0173 } 0174 0175 void KTron::updateStatusbar() { 0176 QString message; 0177 0178 if (!m_tron->running() && m_tron->hasWinner()) { 0179 QString winnerName = m_tron->getPlayer(m_tron->getWinner())->getName(); 0180 0181 message = i18n("%1 has won!", winnerName); 0182 } 0183 else if (m_tron->paused()) { 0184 message = i18n("Game paused"); 0185 } 0186 else { 0187 message = QString(); 0188 } 0189 0190 m_statusBarLabel[0]->setText(message); 0191 0192 if (Settings::gameType() == Settings::EnumGameType::Snake) 0193 { 0194 QString string = QStringLiteral( "%1: %2").arg(m_tron->getPlayer(0)->getName()).arg(m_tron->getPlayer(0)->getScore()); 0195 m_statusBarLabel[1]->setText(string); 0196 m_statusBarLabel[2]->clear(); 0197 } 0198 else 0199 { 0200 for (int i = 0; i < 2; ++i) { 0201 QString name = m_tron->getPlayer(1 - i)->getName(); 0202 int score = m_tron->getPlayer(1 - i)->getScore(); 0203 0204 QString string = QStringLiteral( "%1: %2").arg(name).arg(score); 0205 m_statusBarLabel[i+1]->setText(string); 0206 } 0207 } 0208 } 0209 0210 void KTron::blockPause(bool block) 0211 { 0212 //qCDebug(KSNAKEDUEL_LOG) << "Setting pause button state to: " << !block; 0213 m_pauseButton->setEnabled(!block); 0214 } 0215 0216 void KTron::updateScore() 0217 { 0218 updateStatusbar(); 0219 } 0220 0221 void KTron::changeStatus() { 0222 updateStatusbar(); 0223 0224 if (Settings::gameType() == Settings::EnumGameType::Snake) 0225 { 0226 KGameHighScoreDialog scoreDialog(KGameHighScoreDialog::Score | KGameHighScoreDialog::Name, this); 0227 scoreDialog.initFromDifficulty(KGameDifficulty::global()); 0228 0229 KGameHighScoreDialog::FieldInfo scoreInfo; 0230 scoreInfo[KGameHighScoreDialog::Name] = m_tron->getPlayer(0)->getName(); 0231 scoreInfo[KGameHighScoreDialog::Score].setNum(m_tron->getPlayer(0)->getScore()); 0232 if (scoreDialog.addScore(scoreInfo) != 0) 0233 scoreDialog.exec(); 0234 } 0235 } 0236 0237 void KTron::paletteChange(const QPalette &){ 0238 update(); 0239 m_tron->updatePixmap(); 0240 m_tron->update(); 0241 } 0242 0243 /** 0244 * Show Settings dialog. 0245 */ 0246 void KTron::showSettings(){ 0247 if (KConfigDialog::showDialog(QStringLiteral( "settings" ))) 0248 return; 0249 0250 m_generalConfigDialog = new General(); 0251 0252 if (Settings::gameType() == Settings::EnumGameType::Snake) { 0253 m_generalConfigDialog->namePlayer1Label->setText(i18n("Player Name:")); 0254 m_generalConfigDialog->namePlayer2Label->setText(i18n("Opponent:")); 0255 } 0256 else { 0257 m_generalConfigDialog->namePlayer1Label->setText(i18n("Right player:")); 0258 m_generalConfigDialog->namePlayer2Label->setText(i18n("Left player:")); 0259 } 0260 0261 KConfigDialog *dialog = new KConfigDialog(this, QStringLiteral( "settings" ), Settings::self()); 0262 dialog->addPage(m_generalConfigDialog, i18n("General"), QStringLiteral( "games-config-options" )); 0263 dialog->addPage(new KGameThemeSelector(Renderer::self()->themeProvider(), KGameThemeSelector::EnableNewStuffDownload, dialog), i18n("Theme"), QStringLiteral( "games-config-theme" )); 0264 connect(dialog, &KConfigDialog::settingsChanged, this, &KTron::loadSettings); 0265 connect(dialog, &KConfigDialog::settingsChanged, m_tron, &Tron::loadSettings); 0266 dialog->show(); 0267 } 0268 0269 /** 0270 * Show highscores 0271 */ 0272 void KTron::showHighscores() { 0273 KGameHighScoreDialog scoreDialog(KGameHighScoreDialog::Score | KGameHighScoreDialog::Name, this); 0274 scoreDialog.initFromDifficulty(KGameDifficulty::global()); 0275 scoreDialog.exec(); 0276 } 0277 0278 /** 0279 * Close KTron 0280 */ 0281 void KTron::close() { 0282 Settings::self()->save(); 0283 } 0284 0285 void KTron::closeEvent(QCloseEvent *event) 0286 { 0287 close(); 0288 event->accept(); 0289 } 0290 0291 void KTron::optionsConfigureKeys() 0292 { 0293 KShortcutsDialog::showDialog(actionCollection(), KShortcutsEditor::LetterShortcutsAllowed, this); 0294 } 0295 0296 // Key events 0297 void KTron::keyPressEvent(QKeyEvent *e) 0298 { 0299 if (m_player0Accelerate->shortcuts().contains(e->key())) 0300 { 0301 triggerKey0Accelerate(true); 0302 } 0303 else if (m_player1Accelerate->shortcuts().contains(e->key())) 0304 { 0305 triggerKey1Accelerate(true); 0306 } 0307 } 0308 0309 void KTron::keyReleaseEvent(QKeyEvent *e) 0310 { 0311 if (m_player0Accelerate->shortcuts().contains(e->key())) 0312 { 0313 triggerKey0Accelerate(false); 0314 } 0315 else if (m_player1Accelerate->shortcuts().contains(e->key())) 0316 { 0317 triggerKey1Accelerate(false); 0318 } 0319 } 0320 0321 // Triggers 0322 void KTron::triggerKey0Up(bool b) 0323 { 0324 m_tron->triggerKey(0, KBAction::UP, b); 0325 } 0326 0327 void KTron::triggerKey0Down(bool b) 0328 { 0329 m_tron->triggerKey(0, KBAction::DOWN, b); 0330 } 0331 0332 void KTron::triggerKey0Left(bool b) 0333 { 0334 m_tron->triggerKey(0, KBAction::LEFT, b); 0335 } 0336 0337 void KTron::triggerKey0Right(bool b) 0338 { 0339 m_tron->triggerKey(0, KBAction::RIGHT, b); 0340 } 0341 0342 void KTron::triggerKey0Accelerate(bool b) 0343 { 0344 m_tron->triggerKey(0, KBAction::ACCELERATE, b); 0345 } 0346 0347 void KTron::triggerKey1Up(bool b) 0348 { 0349 m_tron->triggerKey(1, KBAction::UP, b); 0350 } 0351 0352 void KTron::triggerKey1Down(bool b) 0353 { 0354 m_tron->triggerKey(1, KBAction::DOWN, b); 0355 } 0356 0357 void KTron::triggerKey1Left(bool b) 0358 { 0359 m_tron->triggerKey(1, KBAction::LEFT, b); 0360 } 0361 0362 void KTron::triggerKey1Right(bool b) 0363 { 0364 m_tron->triggerKey(1, KBAction::RIGHT, b); 0365 } 0366 0367 void KTron::triggerKey1Accelerate(bool b) 0368 { 0369 m_tron->triggerKey(1, KBAction::ACCELERATE, b); 0370 } 0371 0372 #include "moc_ktron.cpp"