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
46class General : public QWidget, public Ui::General
47{
48public:
49 General(QWidget *parent = 0)
50 : QWidget(parent)
51 {
52 setupUi(this);
53 }
54};
55
56/**
57 * Constuctor
58 */
59KTron::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
161KTron::~KTron()
162{
163 delete m_tron;
164}
165
166void 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
182void 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
217void KTron::blockPause(bool block)
218{
219 //kDebug() << "Setting pause button state to: " << !block;
220 m_pauseButton->setEnabled(!block);
221}
222
223void KTron::updateScore()
224{
225 updateStatusbar();
226}
227
228void 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
244void KTron::paletteChange(const QPalette &){
245 update();
246 m_tron->updatePixmap();
247 m_tron->update();
248}
249
250/**
251 * Show Settings dialog.
252 */
253void 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 */
279void 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 */
288void KTron::close() {
289 Settings::self()->writeConfig();
290}
291
292void KTron::closeEvent(QCloseEvent *event)
293{
294 close();
295 event->accept();
296}
297
298void KTron::optionsConfigureKeys()
299{
300 KShortcutsDialog::configure(actionCollection());
301}
302
303// Key events
304void 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
316void 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
329void KTron::triggerKey0Up(bool b)
330{
331 m_tron->triggerKey(0, KBAction::UP, b);
332}
333
334void KTron::triggerKey0Down(bool b)
335{
336 m_tron->triggerKey(0, KBAction::DOWN, b);
337}
338
339void KTron::triggerKey0Left(bool b)
340{
341 m_tron->triggerKey(0, KBAction::LEFT, b);
342}
343
344void KTron::triggerKey0Right(bool b)
345{
346 m_tron->triggerKey(0, KBAction::RIGHT, b);
347}
348
349void KTron::triggerKey0Accelerate(bool b)
350{
351 m_tron->triggerKey(0, KBAction::ACCELERATE, b);
352}
353
354void KTron::triggerKey1Up(bool b)
355{
356 m_tron->triggerKey(1, KBAction::UP, b);
357}
358
359void KTron::triggerKey1Down(bool b)
360{
361 m_tron->triggerKey(1, KBAction::DOWN, b);
362}
363
364void KTron::triggerKey1Left(bool b)
365{
366 m_tron->triggerKey(1, KBAction::LEFT, b);
367}
368
369void KTron::triggerKey1Right(bool b)
370{
371 m_tron->triggerKey(1, KBAction::RIGHT, b);
372}
373
374void KTron::triggerKey1Accelerate(bool b)
375{
376 m_tron->triggerKey(1, KBAction::ACCELERATE, b);
377}
378
379
380#include "ktron.moc"
381
382