1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the QtCore module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** GNU General Public License Usage
31 ** Alternatively, this file may be used under the terms of the GNU
32 ** General Public License version 3.0 as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL included in the
34 ** packaging of this file. Please review the following information to
35 ** ensure the GNU General Public License version 3.0 requirements will be
36 ** met: http://www.gnu.org/copyleft/gpl.html.
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 //Own
43 #include "states.h"
44 #include "graphicsscene.h"
45 #include "boat.h"
46 #include "submarine.h"
47 #include "torpedo.h"
48 #include "animationmanager.h"
49 #include "progressitem.h"
50 #include "textinformationitem.h"
51
52 //Qt
53 #include <QtGui/QMessageBox>
54 #include <QtGui/QGraphicsView>
55 #include <QtCore/QStateMachine>
56 #include <QtGui/QKeyEventTransition>
57 #include <QtCore/QFinalState>
58
PlayState(GraphicsScene * scene,QState * parent)59 PlayState::PlayState(GraphicsScene *scene, QState *parent)
60 : QState(parent),
61 scene(scene),
62 machine(0),
63 currentLevel(0),
64 score(0)
65 {
66 }
67
~PlayState()68 PlayState::~PlayState()
69 {
70 delete machine;
71 }
72
onEntry(QEvent *)73 void PlayState::onEntry(QEvent *)
74 {
75 //We are now playing?
76 if (machine) {
77 machine->stop();
78 //we hide the information
79 scene->textInformationItem->hide();
80 scene->clearScene();
81 currentLevel = 0;
82 score = 0;
83 delete machine;
84 }
85
86 machine = new QStateMachine;
87
88 //This state is when player is playing
89 LevelState *levelState = new LevelState(scene, this, machine);
90
91 //This state is when the player is actually playing but the game is not paused
92 QState *playingState = new QState(levelState);
93 levelState->setInitialState(playingState);
94
95 //This state is when the game is paused
96 PauseState *pauseState = new PauseState(scene, levelState);
97
98 //We have one view, it receive the key press event
99 QKeyEventTransition *pressPplay = new QKeyEventTransition(scene->views().at(0), QEvent::KeyPress, Qt::Key_P);
100 pressPplay->setTargetState(pauseState);
101 QKeyEventTransition *pressPpause = new QKeyEventTransition(scene->views().at(0), QEvent::KeyPress, Qt::Key_P);
102 pressPpause->setTargetState(playingState);
103
104 //Pause "P" is triggered, the player pause the game
105 playingState->addTransition(pressPplay);
106
107 //To get back playing when the game has been paused
108 pauseState->addTransition(pressPpause);
109
110 //This state is when player have lost
111 LostState *lostState = new LostState(scene, this, machine);
112
113 //This state is when player have won
114 WinState *winState = new WinState(scene, this, machine);
115
116 //The boat has been destroyed then the game is finished
117 levelState->addTransition(scene->boat, SIGNAL(boatExecutionFinished()),lostState);
118
119 //This transition check if we won or not
120 WinTransition *winTransition = new WinTransition(scene, this, winState);
121
122 //The boat has been destroyed then the game is finished
123 levelState->addTransition(winTransition);
124
125 //This state is an animation when the score changed
126 UpdateScoreState *scoreState = new UpdateScoreState(this, levelState);
127
128 //This transition update the score when a submarine die
129 UpdateScoreTransition *scoreTransition = new UpdateScoreTransition(scene, this, levelState);
130 scoreTransition->setTargetState(scoreState);
131
132 //The boat has been destroyed then the game is finished
133 playingState->addTransition(scoreTransition);
134
135 //We go back to play state
136 scoreState->addTransition(playingState);
137
138 //We start playing!!!
139 machine->setInitialState(levelState);
140
141 //Final state
142 QFinalState *final = new QFinalState(machine);
143
144 //This transition is triggered when the player press space after completing a level
145 CustomSpaceTransition *spaceTransition = new CustomSpaceTransition(scene->views().at(0), this, QEvent::KeyPress, Qt::Key_Space);
146 spaceTransition->setTargetState(levelState);
147 winState->addTransition(spaceTransition);
148
149 //We lost we should reach the final state
150 lostState->addTransition(lostState, SIGNAL(finished()), final);
151
152 machine->start();
153 }
154
LevelState(GraphicsScene * scene,PlayState * game,QState * parent)155 LevelState::LevelState(GraphicsScene *scene, PlayState *game, QState *parent) : QState(parent), scene(scene), game(game)
156 {
157 }
onEntry(QEvent *)158 void LevelState::onEntry(QEvent *)
159 {
160 initializeLevel();
161 }
162
initializeLevel()163 void LevelState::initializeLevel()
164 {
165 //we re-init the boat
166 scene->boat->setPos(scene->width()/2, scene->sealLevel() - scene->boat->size().height());
167 scene->boat->setCurrentSpeed(0);
168 scene->boat->setCurrentDirection(Boat::None);
169 scene->boat->setBombsLaunched(0);
170 scene->boat->show();
171 scene->setFocusItem(scene->boat, Qt::OtherFocusReason);
172 scene->boat->run();
173
174 scene->progressItem->setScore(game->score);
175 scene->progressItem->setLevel(game->currentLevel + 1);
176
177 GraphicsScene::LevelDescription currentLevelDescription = scene->levelsData.value(game->currentLevel);
178
179 for (int i = 0; i < currentLevelDescription.submarines.size(); ++i ) {
180
181 QPair<int,int> subContent = currentLevelDescription.submarines.at(i);
182 GraphicsScene::SubmarineDescription submarineDesc = scene->submarinesData.at(subContent.first);
183
184 for (int j = 0; j < subContent.second; ++j ) {
185 SubMarine *sub = new SubMarine(submarineDesc.type, submarineDesc.name, submarineDesc.points);
186 scene->addItem(sub);
187 int random = (qrand() % 15 + 1);
188 qreal x = random == 13 || random == 5 ? 0 : scene->width() - sub->size().width();
189 qreal y = scene->height() -(qrand() % 150 + 1) - sub->size().height();
190 sub->setPos(x,y);
191 sub->setCurrentDirection(x == 0 ? SubMarine::Right : SubMarine::Left);
192 sub->setCurrentSpeed(qrand() % 3 + 1);
193 }
194 }
195 }
196
197 /** Pause State */
PauseState(GraphicsScene * scene,QState * parent)198 PauseState::PauseState(GraphicsScene *scene, QState *parent) : QState(parent),scene(scene)
199 {
200 }
onEntry(QEvent *)201 void PauseState::onEntry(QEvent *)
202 {
203 AnimationManager::self()->pauseAll();
204 scene->boat->setEnabled(false);
205 }
onExit(QEvent *)206 void PauseState::onExit(QEvent *)
207 {
208 AnimationManager::self()->resumeAll();
209 scene->boat->setEnabled(true);
210 scene->boat->setFocus();
211 }
212
213 /** Lost State */
LostState(GraphicsScene * scene,PlayState * game,QState * parent)214 LostState::LostState(GraphicsScene *scene, PlayState *game, QState *parent) : QState(parent), scene(scene), game(game)
215 {
216 }
217
onEntry(QEvent *)218 void LostState::onEntry(QEvent *)
219 {
220 //The message to display
221 QString message = QString("You lose on level %1. Your score is %2.").arg(game->currentLevel+1).arg(game->score);
222
223 //We set the level back to 0
224 game->currentLevel = 0;
225
226 //We set the score back to 0
227 game->score = 0;
228
229 //We clear the scene
230 scene->clearScene();
231
232 //We inform the player
233 scene->textInformationItem->setMessage(message);
234 scene->textInformationItem->show();
235 }
236
onExit(QEvent *)237 void LostState::onExit(QEvent *)
238 {
239 //we hide the information
240 scene->textInformationItem->hide();
241 }
242
243 /** Win State */
WinState(GraphicsScene * scene,PlayState * game,QState * parent)244 WinState::WinState(GraphicsScene *scene, PlayState *game, QState *parent) : QState(parent), scene(scene), game(game)
245 {
246 }
247
onEntry(QEvent *)248 void WinState::onEntry(QEvent *)
249 {
250 //We clear the scene
251 scene->clearScene();
252
253 QString message;
254 if (scene->levelsData.size() - 1 != game->currentLevel) {
255 message = QString("You win the level %1. Your score is %2.\nPress Space to continue.").arg(game->currentLevel+1).arg(game->score);
256 //We increment the level number
257 game->currentLevel++;
258 } else {
259 message = QString("You finish the game on level %1. Your score is %2.").arg(game->currentLevel+1).arg(game->score);
260 //We set the level back to 0
261 game->currentLevel = 0;
262 //We set the score back to 0
263 game->score = 0;
264 }
265
266 //We inform the player
267 scene->textInformationItem->setMessage(message);
268 scene->textInformationItem->show();
269 }
270
onExit(QEvent *)271 void WinState::onExit(QEvent *)
272 {
273 //we hide the information
274 scene->textInformationItem->hide();
275 }
276
277 /** UpdateScore State */
UpdateScoreState(PlayState * g,QState * parent)278 UpdateScoreState::UpdateScoreState(PlayState *g, QState *parent) : QState(parent), game(g)
279 {
280 }
281
282 /** Win transition */
UpdateScoreTransition(GraphicsScene * scene,PlayState * game,QAbstractState * target)283 UpdateScoreTransition::UpdateScoreTransition(GraphicsScene *scene, PlayState *game, QAbstractState *target)
284 : QSignalTransition(scene,SIGNAL(subMarineDestroyed(int))),
285 game(game), scene(scene)
286 {
287 setTargetState(target);
288 }
289
eventTest(QEvent * event)290 bool UpdateScoreTransition::eventTest(QEvent *event)
291 {
292 if (!QSignalTransition::eventTest(event))
293 return false;
294 QStateMachine::SignalEvent *se = static_cast<QStateMachine::SignalEvent*>(event);
295 game->score += se->arguments().at(0).toInt();
296 scene->progressItem->setScore(game->score);
297 return true;
298 }
299
300 /** Win transition */
WinTransition(GraphicsScene * scene,PlayState * game,QAbstractState * target)301 WinTransition::WinTransition(GraphicsScene *scene, PlayState *game, QAbstractState *target)
302 : QSignalTransition(scene,SIGNAL(allSubMarineDestroyed(int))),
303 game(game), scene(scene)
304 {
305 setTargetState(target);
306 }
307
eventTest(QEvent * event)308 bool WinTransition::eventTest(QEvent *event)
309 {
310 if (!QSignalTransition::eventTest(event))
311 return false;
312 QStateMachine::SignalEvent *se = static_cast<QStateMachine::SignalEvent*>(event);
313 game->score += se->arguments().at(0).toInt();
314 scene->progressItem->setScore(game->score);
315 return true;
316 }
317
318 /** Space transition */
CustomSpaceTransition(QWidget * widget,PlayState * game,QEvent::Type type,int key)319 CustomSpaceTransition::CustomSpaceTransition(QWidget *widget, PlayState *game, QEvent::Type type, int key)
320 : QKeyEventTransition(widget, type, key),
321 game(game)
322 {
323 }
324
eventTest(QEvent * event)325 bool CustomSpaceTransition::eventTest(QEvent *event)
326 {
327 if (!QKeyEventTransition::eventTest(event))
328 return false;
329 return (game->currentLevel != 0);
330 }
331