Sub-Attaq▲
Sélectionnez
/**
**************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** BSD License Usage
** Alternatively, you may use this file under the terms of the BSD license
** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
***************************************************************************
*/
//Own
#include
"states.h"
#include
"graphicsscene.h"
#include
"boat.h"
#include
"submarine.h"
#include
"torpedo.h"
#include
"animationmanager.h"
#include
"progressitem.h"
#include
"textinformationitem.h"
//Qt
#include <QtWidgets/QMessageBox>
#include <QtWidgets/QGraphicsView>
#include <QtCore/QStateMachine>
#include <QtWidgets/QKeyEventTransition>
#include <QtCore/QFinalState>
#include <QtCore/QRandomGenerator>
PlayState::
PlayState(GraphicsScene *
scene, QState *
parent)
:
QState(parent),
scene(scene),
machine(0
),
currentLevel(0
),
score(0
)
{
}
PlayState::
~
PlayState()
{
delete
machine;
}
void
PlayState::
onEntry(QEvent *
)
{
//We are now playing?
if
(machine) {
machine-&
gt;stop();
//we hide the information
scene-&
gt;textInformationItem-&
gt;hide();
scene-&
gt;clearScene();
currentLevel =
0
;
score =
0
;
delete
machine;
}
machine =
new
QStateMachine;
//This state is when player is playing
LevelState *
levelState =
new
LevelState(scene, this
, machine);
//This state is when the player is actually playing but the game is not paused
QState *
playingState =
new
QState(levelState);
levelState-&
gt;setInitialState(playingState);
//This state is when the game is paused
PauseState *
pauseState =
new
PauseState(scene, levelState);
//We have one view, it receive the key press event
QKeyEventTransition *
pressPplay =
new
QKeyEventTransition(scene-&
gt;views().at(0
), QEvent::
KeyPress, Qt::
Key_P);
pressPplay-&
gt;setTargetState(pauseState);
QKeyEventTransition *
pressPpause =
new
QKeyEventTransition(scene-&
gt;views().at(0
), QEvent::
KeyPress, Qt::
Key_P);
pressPpause-&
gt;setTargetState(playingState);
//Pause "P" is triggered, the player pause the game
playingState-&
gt;addTransition(pressPplay);
//To get back playing when the game has been paused
pauseState-&
gt;addTransition(pressPpause);
//This state is when player have lost
LostState *
lostState =
new
LostState(scene, this
, machine);
//This state is when player have won
WinState *
winState =
new
WinState(scene, this
, machine);
//The boat has been destroyed then the game is finished
levelState-&
gt;addTransition(scene-&
gt;boat, SIGNAL(boatExecutionFinished()),lostState);
//This transition check if we won or not
WinTransition *
winTransition =
new
WinTransition(scene, this
, winState);
//The boat has been destroyed then the game is finished
levelState-&
gt;addTransition(winTransition);
//This state is an animation when the score changed
UpdateScoreState *
scoreState =
new
UpdateScoreState(levelState);
//This transition update the score when a submarine die
UpdateScoreTransition *
scoreTransition =
new
UpdateScoreTransition(scene, this
, levelState);
scoreTransition-&
gt;setTargetState(scoreState);
//The boat has been destroyed then the game is finished
playingState-&
gt;addTransition(scoreTransition);
//We go back to play state
scoreState-&
gt;addTransition(playingState);
//We start playing!!!
machine-&
gt;setInitialState(levelState);
//Final state
QFinalState *
final
=
new
QFinalState(machine);
//This transition is triggered when the player press space after completing a level
CustomSpaceTransition *
spaceTransition =
new
CustomSpaceTransition(scene-&
gt;views().at(0
), this
, QEvent::
KeyPress, Qt::
Key_Space);
spaceTransition-&
gt;setTargetState(levelState);
winState-&
gt;addTransition(spaceTransition);
//We lost we should reach the final state
lostState-&
gt;addTransition(lostState, SIGNAL(finished()), final
);
machine-&
gt;start();
}
LevelState::
LevelState(GraphicsScene *
scene, PlayState *
game, QState *
parent) : QState(parent), scene(scene), game(game)
{
}
void
LevelState::
onEntry(QEvent *
)
{
initializeLevel();
}
void
LevelState::
initializeLevel()
{
//we re-init the boat
scene-&
gt;boat-&
gt;setPos(scene-&
gt;width()/
2
, scene-&
gt;sealLevel() -
scene-&
gt;boat-&
gt;size().height());
scene-&
gt;boat-&
gt;setCurrentSpeed(0
);
scene-&
gt;boat-&
gt;setCurrentDirection(Boat::
None);
scene-&
gt;boat-&
gt;setBombsLaunched(0
);
scene-&
gt;boat-&
gt;show();
scene-&
gt;setFocusItem(scene-&
gt;boat, Qt::
OtherFocusReason);
scene-&
gt;boat-&
gt;run();
scene-&
gt;progressItem-&
gt;setScore(game-&
gt;score);
scene-&
gt;progressItem-&
gt;setLevel(game-&
gt;currentLevel +
1
);
GraphicsScene::
LevelDescription currentLevelDescription =
scene-&
gt;levelsData.value(game-&
gt;currentLevel);
for
(int
i =
0
; i &
lt; currentLevelDescription.submarines.size(); ++
i ) {
QPair&
lt;int
,int
&
gt; subContent =
currentLevelDescription.submarines.at(i);
GraphicsScene::
SubmarineDescription submarineDesc =
scene-&
gt;submarinesData.at(subContent.first);
for
(int
j =
0
; j &
lt; subContent.second; ++
j ) {
SubMarine *
sub =
new
SubMarine(submarineDesc.type, submarineDesc.name, submarineDesc.points);
scene-&
gt;addItem(sub);
int
random =
QRandomGenerator::
global()-&
gt;bounded(15
) +
1
;
qreal x =
random ==
13
||
random ==
5
? 0
: scene-&
gt;width() -
sub-&
gt;size().width();
qreal y =
scene-&
gt;height() -
(QRandomGenerator::
global()-&
gt;bounded(150
) +
1
) -
sub-&
gt;size().height();
sub-&
gt;setPos(x,y);
sub-&
gt;setCurrentDirection(x ==
0
? SubMarine::
Right : SubMarine::
Left);
sub-&
gt;setCurrentSpeed(QRandomGenerator::
global()-&
gt;bounded(3
) +
1
);
}
}
}
/**
Pause State
*/
PauseState::
PauseState(GraphicsScene *
scene, QState *
parent) : QState(parent),scene(scene)
{
}
void
PauseState::
onEntry(QEvent *
)
{
AnimationManager::
self()-&
gt;pauseAll();
scene-&
gt;boat-&
gt;setEnabled(false
);
}
void
PauseState::
onExit(QEvent *
)
{
AnimationManager::
self()-&
gt;resumeAll();
scene-&
gt;boat-&
gt;setEnabled(true
);
scene-&
gt;boat-&
gt;setFocus();
}
/**
Lost State
*/
LostState::
LostState(GraphicsScene *
scene, PlayState *
game, QState *
parent) : QState(parent), scene(scene), game(game)
{
}
void
LostState::
onEntry(QEvent *
)
{
//The message to display
QString message =
QString("You lose on level %1. Your score is %2."
).arg(game-&
gt;currentLevel+
1
).arg(game-&
gt;score);
//We set the level back to 0
game-&
gt;currentLevel =
0
;
//We set the score back to 0
game-&
gt;score =
0
;
//We clear the scene
scene-&
gt;clearScene();
//We inform the player
scene-&
gt;textInformationItem-&
gt;setMessage(message);
scene-&
gt;textInformationItem-&
gt;show();
}
void
LostState::
onExit(QEvent *
)
{
//we hide the information
scene-&
gt;textInformationItem-&
gt;hide();
}
/**
Win State
*/
WinState::
WinState(GraphicsScene *
scene, PlayState *
game, QState *
parent) : QState(parent), scene(scene), game(game)
{
}
void
WinState::
onEntry(QEvent *
)
{
//We clear the scene
scene-&
gt;clearScene();
QString message;
if
(scene-&
gt;levelsData.size() -
1
!=
game-&
gt;currentLevel) {
message =
QString("You win the level %1. Your score is %2.
\n
Press Space to continue."
).arg(game-&
gt;currentLevel+
1
).arg(game-&
gt;score);
//We increment the level number
game-&
gt;currentLevel++
;
}
else
{
message =
QString("You finish the game on level %1. Your score is %2."
).arg(game-&
gt;currentLevel+
1
).arg(game-&
gt;score);
//We set the level back to 0
game-&
gt;currentLevel =
0
;
//We set the score back to 0
game-&
gt;score =
0
;
}
//We inform the player
scene-&
gt;textInformationItem-&
gt;setMessage(message);
scene-&
gt;textInformationItem-&
gt;show();
}
void
WinState::
onExit(QEvent *
)
{
//we hide the information
scene-&
gt;textInformationItem-&
gt;hide();
}
/**
UpdateScore State
*/
UpdateScoreState::
UpdateScoreState(QState *
parent) : QState(parent)
{
}
/**
Win transition
*/
UpdateScoreTransition::
UpdateScoreTransition(GraphicsScene *
scene, PlayState *
game, QAbstractState *
target)
:
QSignalTransition(scene,SIGNAL(subMarineDestroyed(int
))),
game(game), scene(scene)
{
setTargetState(target);
}
bool
UpdateScoreTransition::
eventTest(QEvent *
event)
{
if
(!
QSignalTransition::
eventTest(event))
return
false
;
QStateMachine::
SignalEvent *
se =
static_cast
&
lt;QStateMachine::
SignalEvent*&
gt;(event);
game-&
gt;score +=
se-&
gt;arguments().at(0
).toInt();
scene-&
gt;progressItem-&
gt;setScore(game-&
gt;score);
return
true
;
}
/**
Win transition
*/
WinTransition::
WinTransition(GraphicsScene *
scene, PlayState *
game, QAbstractState *
target)
:
QSignalTransition(scene,SIGNAL(allSubMarineDestroyed(int
))),
game(game), scene(scene)
{
setTargetState(target);
}
bool
WinTransition::
eventTest(QEvent *
event)
{
if
(!
QSignalTransition::
eventTest(event))
return
false
;
QStateMachine::
SignalEvent *
se =
static_cast
&
lt;QStateMachine::
SignalEvent*&
gt;(event);
game-&
gt;score +=
se-&
gt;arguments().at(0
).toInt();
scene-&
gt;progressItem-&
gt;setScore(game-&
gt;score);
return
true
;
}
/**
Space transition
*/
CustomSpaceTransition::
CustomSpaceTransition(QWidget *
widget, PlayState *
game, QEvent::
Type type, int
key)
:
QKeyEventTransition(widget, type, key),
game(game)
{
}
bool
CustomSpaceTransition::
eventTest(QEvent *
event)
{
if
(!
QKeyEventTransition::
eventTest(event))
return
false
;
return
(game-&
gt;currentLevel !=
0
);
}