1 | /********************************************************************************** |
2 | This file is part of the game 'KTron' |
3 | |
4 | Copyright (C) 1998-2000 by Matthias Kiefer <matthias.kiefer@gmx.de> |
5 | Copyright (C) 2005 Benjamin C. Meyer <ben at meyerhome dot net> |
6 | Copyright (C) 2008-2009 Stas Verberkt <legolas at legolasweb dot nl> |
7 | |
8 | This program is free software; you can redistribute it and/or modify |
9 | it under the terms of the GNU General Public License as published by |
10 | the Free Software Foundation; either version 2 of the License, or |
11 | (at your option) any later version. |
12 | |
13 | This program is distributed in the hope that it will be useful, |
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | GNU General Public License for more details. |
17 | |
18 | You should have received a copy of the GNU General Public License |
19 | along with this program; if not, write to the Free Software |
20 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
21 | |
22 | *******************************************************************************/ |
23 | |
24 | #include "ktron.h" |
25 | #include "renderer.h" |
26 | #include "settings.h" |
27 | #include "ui_general.h" |
28 | |
29 | #include <KConfigDialog> |
30 | #include <KLocale> |
31 | #include <KMessageBox> |
32 | #include <KAction> |
33 | #include <KActionCollection> |
34 | #include <KStandardGameAction> |
35 | #include <KScoreDialog> |
36 | #include <KgDifficulty> |
37 | #include <KShortcutsDialog> |
38 | #include <KStatusBar> |
39 | #include <KToggleAction> |
40 | #include <KApplication> |
41 | |
42 | #define USE_UNSTABLE_LIBKDEGAMESPRIVATE_API |
43 | #include <libkdegamesprivate/kgamethemeselector.h> |
44 | |
45 | //UI |
46 | class General : public QWidget, public Ui::General |
47 | { |
48 | public: |
49 | General(QWidget *parent = 0) |
50 | : QWidget(parent) |
51 | { |
52 | setupUi(this); |
53 | } |
54 | }; |
55 | |
56 | /** |
57 | * Constuctor |
58 | */ |
59 | KTron::KTron(QWidget *parent) : KXmlGuiWindow(parent, KDE_DEFAULT_WINDOWFLAGS) { |
60 | m_tron = new Tron(this); |
61 | connect(m_tron,SIGNAL(gameEnds()),SLOT(changeStatus())); |
62 | connect(m_tron,SIGNAL(updatedScore()),SLOT(updateScore())); |
63 | connect(m_tron,SIGNAL(pauseBlocked(bool)),SLOT(blockPause(bool))); |
64 | m_tron->setMinimumSize(700,420); |
65 | setCentralWidget(m_tron); |
66 | |
67 | // create statusbar |
68 | statusBar()->insertItem(QLatin1String( "abcdefghijklmnopqrst: 0 " ),ID_STATUS_BASE + 1); |
69 | statusBar()->insertItem(QLatin1String( "abcdefghijklmnopqrst: 0 " ),ID_STATUS_BASE + 2); |
70 | |
71 | // We match up keyboard events ourselves in Tron::keyPressEvent() |
72 | // We must disable the actions, otherwise we don't get the keyPressEvent's |
73 | |
74 | m_player0Up = actionCollection()->addAction( QLatin1String( "Pl1Up" )); |
75 | m_player0Up->setText(i18n("Right Player / KSnake: Up" )); |
76 | m_player0Up->setShortcut(Qt::Key_Up); |
77 | connect(m_player0Up, SIGNAL(triggered(bool)), SLOT(triggerKey0Up(bool))); |
78 | addAction(m_player0Up); |
79 | |
80 | m_player0Down = actionCollection()->addAction( QLatin1String( "Pl1Down" )); |
81 | m_player0Down->setText(i18n("Right Player / KSnake: Down" )); |
82 | m_player0Down->setShortcut(Qt::Key_Down); |
83 | connect(m_player0Down, SIGNAL(triggered(bool)), SLOT(triggerKey0Down(bool))); |
84 | addAction(m_player0Down); |
85 | |
86 | m_player0Right = actionCollection()->addAction( QLatin1String( "Pl1Right" )); |
87 | m_player0Right->setText(i18n("Right Player / KSnake: Right" )); |
88 | m_player0Right->setShortcut(Qt::Key_Right); |
89 | connect(m_player0Right, SIGNAL(triggered(bool)), SLOT(triggerKey0Right(bool))); |
90 | addAction(m_player0Right); |
91 | |
92 | m_player0Left = actionCollection()->addAction( QLatin1String( "Pl1Left" )); |
93 | m_player0Left->setText(i18n("Right Player / KSnake: Left" )); |
94 | m_player0Left->setShortcut(Qt::Key_Left); |
95 | connect(m_player0Left, SIGNAL(triggered(bool)), SLOT(triggerKey0Left(bool))); |
96 | addAction(m_player0Left); |
97 | |
98 | m_player0Accelerate = actionCollection()->addAction( QLatin1String( "Pl1Ac" )); |
99 | m_player0Accelerate->setText(i18n("Right Player: Accelerator" )); |
100 | m_player0Accelerate->setShortcut(Qt::Key_0); |
101 | m_player0Accelerate->setEnabled(false); // Alternate handling, because of up/down events |
102 | addAction(m_player0Accelerate); |
103 | |
104 | m_player1Up = actionCollection()->addAction( QLatin1String( "Pl2Up" )); |
105 | m_player1Up->setText(i18n("Left Player: Up" )); |
106 | m_player1Up->setShortcut(Qt::Key_W); |
107 | connect(m_player1Up, SIGNAL(triggered(bool)), SLOT(triggerKey1Up(bool))); |
108 | addAction(m_player1Up); |
109 | |
110 | m_player1Down = actionCollection()->addAction( QLatin1String( "Pl2Down" )); |
111 | m_player1Down->setText(i18n("Left Player: Down" )); |
112 | m_player1Down->setShortcut(Qt::Key_S); |
113 | connect(m_player1Down, SIGNAL(triggered(bool)), SLOT(triggerKey1Down(bool))); |
114 | addAction(m_player1Down); |
115 | |
116 | m_player1Right = actionCollection()->addAction( QLatin1String( "Pl2Right" ));; |
117 | m_player1Right->setText(i18n("Left Player: Right" )); |
118 | m_player1Right->setShortcut(Qt::Key_D); |
119 | connect(m_player1Right, SIGNAL(triggered(bool)), SLOT(triggerKey1Right(bool))); |
120 | addAction(m_player1Right); |
121 | |
122 | m_player1Left = actionCollection()->addAction( QLatin1String( "Pl2Left" )); |
123 | m_player1Left->setText(i18n("Left Player: Left" )); |
124 | m_player1Left->setShortcut(Qt::Key_A); |
125 | connect(m_player1Left, SIGNAL(triggered(bool)), SLOT(triggerKey1Left(bool))); |
126 | addAction(m_player1Left); |
127 | |
128 | m_player1Accelerate = actionCollection()->addAction( QLatin1String( "Pl2Ac" )); |
129 | m_player1Accelerate->setText(i18n("Left Player: Accelerator" )); |
130 | m_player1Accelerate->setShortcut(Qt::Key_Q); |
131 | m_player1Accelerate->setEnabled(false); // Alternate handling, because of up/down events |
132 | addAction(m_player1Accelerate); |
133 | |
134 | // Pause |
135 | m_pauseButton = KStandardGameAction::pause(m_tron, SLOT(togglePause()), actionCollection()); |
136 | m_pauseButton->setEnabled(false); |
137 | // New |
138 | KStandardGameAction::gameNew(m_tron, SLOT(newGame()), actionCollection()); |
139 | // Quit |
140 | KStandardGameAction::quit(kapp, SLOT(quit()), actionCollection()); |
141 | // Settings |
142 | KStandardAction::preferences(this, SLOT(showSettings()), actionCollection()); |
143 | // Configure keys |
144 | KStandardAction::keyBindings(this, SLOT(optionsConfigureKeys()), actionCollection()); |
145 | // Highscores |
146 | KStandardGameAction::highscores(this, SLOT(showHighscores()), actionCollection()); |
147 | |
148 | //difficulty |
149 | Kg::difficulty()->addStandardLevelRange( |
150 | KgDifficultyLevel::VeryEasy, KgDifficultyLevel::VeryHard, |
151 | KgDifficultyLevel::Easy //default |
152 | ); |
153 | KgDifficultyGUI::init(this); |
154 | connect(Kg::difficulty(), SIGNAL(currentLevelChanged(const KgDifficultyLevel*)), m_tron, SLOT(loadSettings())); |
155 | |
156 | setupGUI( KXmlGuiWindow::Keys | StatusBar | Save | Create); |
157 | loadSettings(); |
158 | m_tron->loadSettings(); |
159 | } |
160 | |
161 | KTron::~KTron() |
162 | { |
163 | delete m_tron; |
164 | } |
165 | |
166 | void KTron::loadSettings() { |
167 | if (!Renderer::self()->loadTheme(Settings::theme())) |
168 | { |
169 | KMessageBox::error(this, i18n("Failed to load \"%1\" theme. Please check your installation." , Settings::theme())); |
170 | } |
171 | |
172 | m_tron->getPlayer(0)->setName(Settings::namePlayer1()); |
173 | m_tron->getPlayer(1)->setName(Settings::namePlayer2()); |
174 | Settings::setNamePlayer1(m_tron->getPlayer(0)->getName()); |
175 | if (!m_tron->getPlayer(1)->isComputer()) { |
176 | Settings::setNamePlayer2(m_tron->getPlayer(1)->getName()); |
177 | } |
178 | |
179 | updateStatusbar(); |
180 | } |
181 | |
182 | void KTron::updateStatusbar() { |
183 | QString message; |
184 | |
185 | if (!m_tron->running() && m_tron->hasWinner()) { |
186 | QString winnerName = m_tron->getPlayer(m_tron->getWinner())->getName(); |
187 | |
188 | message = i18n("%1 has won!" , winnerName); |
189 | } |
190 | else if (m_tron->paused()) { |
191 | message = i18n("Game paused" ); |
192 | } |
193 | else { |
194 | message = QString(); |
195 | } |
196 | |
197 | statusBar()->showMessage(message); |
198 | |
199 | if (Settings::gameType() == Settings::EnumGameType::Snake) |
200 | { |
201 | QString string = QString::fromLatin1( "%1: %2" ).arg(m_tron->getPlayer(0)->getName()).arg(m_tron->getPlayer(0)->getScore()); |
202 | statusBar()->changeItem(string, ID_STATUS_BASE + 1); |
203 | statusBar()->changeItem(QString(), ID_STATUS_BASE + 2); |
204 | } |
205 | else |
206 | { |
207 | for (int i = 0; i < 2; ++i) { |
208 | QString name = m_tron->getPlayer(1 - i)->getName(); |
209 | int score = m_tron->getPlayer(1 - i)->getScore(); |
210 | |
211 | QString string = QString::fromLatin1( "%1: %2" ).arg(name).arg(score); |
212 | statusBar()->changeItem(string, ID_STATUS_BASE + i + 1); |
213 | } |
214 | } |
215 | } |
216 | |
217 | void KTron::blockPause(bool block) |
218 | { |
219 | //kDebug() << "Setting pause button state to: " << !block; |
220 | m_pauseButton->setEnabled(!block); |
221 | } |
222 | |
223 | void KTron::updateScore() |
224 | { |
225 | updateStatusbar(); |
226 | } |
227 | |
228 | void KTron::changeStatus() { |
229 | updateStatusbar(); |
230 | |
231 | if (Settings::gameType() == Settings::EnumGameType::Snake) |
232 | { |
233 | KScoreDialog scoreDialog(KScoreDialog::Score | KScoreDialog::Name, this); |
234 | scoreDialog.initFromDifficulty(Kg::difficulty()); |
235 | |
236 | KScoreDialog::FieldInfo scoreInfo; |
237 | scoreInfo[KScoreDialog::Name] = m_tron->getPlayer(0)->getName(); |
238 | scoreInfo[KScoreDialog::Score].setNum(m_tron->getPlayer(0)->getScore()); |
239 | if (scoreDialog.addScore(scoreInfo) != 0) |
240 | scoreDialog.exec(); |
241 | } |
242 | } |
243 | |
244 | void KTron::paletteChange(const QPalette &){ |
245 | update(); |
246 | m_tron->updatePixmap(); |
247 | m_tron->update(); |
248 | } |
249 | |
250 | /** |
251 | * Show Settings dialog. |
252 | */ |
253 | void KTron::showSettings(){ |
254 | if (KConfigDialog::showDialog(QLatin1String( "settings" ))) |
255 | return; |
256 | |
257 | m_generalConfigDialog = new General(); |
258 | |
259 | if (Settings::gameType() == Settings::EnumGameType::Snake) { |
260 | m_generalConfigDialog->namePlayer1Label->setText(i18n("Player Name:" )); |
261 | m_generalConfigDialog->namePlayer2Label->setText(i18n("Opponent:" )); |
262 | } |
263 | else { |
264 | m_generalConfigDialog->namePlayer1Label->setText(i18n("Right Player:" )); |
265 | m_generalConfigDialog->namePlayer2Label->setText(i18n("Left Player:" )); |
266 | } |
267 | |
268 | KConfigDialog *dialog = new KConfigDialog(this, QLatin1String( "settings" ), Settings::self()); |
269 | dialog->addPage(m_generalConfigDialog, i18n("General" ), QLatin1String( "games-config-options" )); |
270 | dialog->addPage(new KGameThemeSelector(dialog, Settings::self(), KGameThemeSelector::NewStuffEnableDownload), i18n("Theme" ), QLatin1String( "games-config-theme" )); |
271 | connect(dialog, SIGNAL(settingsChanged(QString)), this, SLOT(loadSettings())); |
272 | connect(dialog, SIGNAL(settingsChanged(QString)), m_tron, SLOT(loadSettings())); |
273 | dialog->show(); |
274 | } |
275 | |
276 | /** |
277 | * Show highscores |
278 | */ |
279 | void KTron::showHighscores() { |
280 | KScoreDialog scoreDialog(KScoreDialog::Score | KScoreDialog::Name, this); |
281 | scoreDialog.initFromDifficulty(Kg::difficulty()); |
282 | scoreDialog.exec(); |
283 | } |
284 | |
285 | /** |
286 | * Close KTron |
287 | */ |
288 | void KTron::close() { |
289 | Settings::self()->writeConfig(); |
290 | } |
291 | |
292 | void KTron::closeEvent(QCloseEvent *event) |
293 | { |
294 | close(); |
295 | event->accept(); |
296 | } |
297 | |
298 | void KTron::optionsConfigureKeys() |
299 | { |
300 | KShortcutsDialog::configure(actionCollection()); |
301 | } |
302 | |
303 | // Key events |
304 | void KTron::keyPressEvent(QKeyEvent *e) |
305 | { |
306 | if (m_player0Accelerate->shortcuts().contains(e->key())) |
307 | { |
308 | triggerKey0Accelerate(true); |
309 | } |
310 | else if (m_player1Accelerate->shortcuts().contains(e->key())) |
311 | { |
312 | triggerKey1Accelerate(true); |
313 | } |
314 | } |
315 | |
316 | void KTron::keyReleaseEvent(QKeyEvent *e) |
317 | { |
318 | if (m_player0Accelerate->shortcuts().contains(e->key())) |
319 | { |
320 | triggerKey0Accelerate(false); |
321 | } |
322 | else if (m_player1Accelerate->shortcuts().contains(e->key())) |
323 | { |
324 | triggerKey1Accelerate(false); |
325 | } |
326 | } |
327 | |
328 | // Triggers |
329 | void KTron::triggerKey0Up(bool b) |
330 | { |
331 | m_tron->triggerKey(0, KBAction::UP, b); |
332 | } |
333 | |
334 | void KTron::triggerKey0Down(bool b) |
335 | { |
336 | m_tron->triggerKey(0, KBAction::DOWN, b); |
337 | } |
338 | |
339 | void KTron::triggerKey0Left(bool b) |
340 | { |
341 | m_tron->triggerKey(0, KBAction::LEFT, b); |
342 | } |
343 | |
344 | void KTron::triggerKey0Right(bool b) |
345 | { |
346 | m_tron->triggerKey(0, KBAction::RIGHT, b); |
347 | } |
348 | |
349 | void KTron::triggerKey0Accelerate(bool b) |
350 | { |
351 | m_tron->triggerKey(0, KBAction::ACCELERATE, b); |
352 | } |
353 | |
354 | void KTron::triggerKey1Up(bool b) |
355 | { |
356 | m_tron->triggerKey(1, KBAction::UP, b); |
357 | } |
358 | |
359 | void KTron::triggerKey1Down(bool b) |
360 | { |
361 | m_tron->triggerKey(1, KBAction::DOWN, b); |
362 | } |
363 | |
364 | void KTron::triggerKey1Left(bool b) |
365 | { |
366 | m_tron->triggerKey(1, KBAction::LEFT, b); |
367 | } |
368 | |
369 | void KTron::triggerKey1Right(bool b) |
370 | { |
371 | m_tron->triggerKey(1, KBAction::RIGHT, b); |
372 | } |
373 | |
374 | void KTron::triggerKey1Accelerate(bool b) |
375 | { |
376 | m_tron->triggerKey(1, KBAction::ACCELERATE, b); |
377 | } |
378 | |
379 | |
380 | #include "ktron.moc" |
381 | |
382 | |