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
"boat.h"
#include
"boat_p.h"
#include
"bomb.h"
#include
"pixmapitem.h"
#include
"graphicsscene.h"
#include
"animationmanager.h"
#include
"qanimationstate.h"
//Qt
#include <QtCore/QPropertyAnimation>
#include <QtCore/QStateMachine>
#include <QtCore/QHistoryState>
#include <QtCore/QFinalState>
#include <QtCore/QState>
#include <QtCore/QSequentialAnimationGroup>
static
QAbstractAnimation *
setupDestroyAnimation(Boat *
boat)
{
QSequentialAnimationGroup *
group =
new
QSequentialAnimationGroup(boat);
for
(int
i =
1
; i &
lt;=
4
; i++
) {
PixmapItem *
step =
new
PixmapItem(QString("explosion/boat/step%1"
).arg(i),GraphicsScene::
Big, boat);
step-&
gt;setZValue(6
);
step-&
gt;setOpacity(0
);
//fade-in
QPropertyAnimation *
anim =
new
QPropertyAnimation(step, "opacity"
);
anim-&
gt;setEndValue(1
);
anim-&
gt;setDuration(100
);
group-&
gt;insertAnimation(i-
1
, anim);
//and then fade-out
QPropertyAnimation *
anim2 =
new
QPropertyAnimation(step, "opacity"
);
anim2-&
gt;setEndValue(0
);
anim2-&
gt;setDuration(100
);
group-&
gt;addAnimation(anim2);
}
AnimationManager::
self()-&
gt;registerAnimation(group);
return
group;
}
Boat::
Boat() : PixmapItem(QString("boat"
), GraphicsScene::
Big),
speed(0
), bombsAlreadyLaunched(0
), direction(Boat::
None), movementAnimation(0
)
{
setZValue(4
);
setFlags(QGraphicsItem::
ItemIsFocusable);
//The movement animation used to animate the boat
movementAnimation =
new
QPropertyAnimation(this
, "pos"
);
//The destroy animation used to explode the boat
destroyAnimation =
setupDestroyAnimation(this
);
//We setup the state machine of the boat
machine =
new
QStateMachine(this
);
QState *
moving =
new
QState(machine);
StopState *
stopState =
new
StopState(this
, moving);
machine-&
gt;setInitialState(moving);
moving-&
gt;setInitialState(stopState);
MoveStateRight *
moveStateRight =
new
MoveStateRight(this
, moving);
MoveStateLeft *
moveStateLeft =
new
MoveStateLeft(this
, moving);
LaunchStateRight *
launchStateRight =
new
LaunchStateRight(this
, machine);
LaunchStateLeft *
launchStateLeft =
new
LaunchStateLeft(this
, machine);
//then setup the transitions for the rightMove state
KeyStopTransition *
leftStopRight =
new
KeyStopTransition(this
, QEvent::
KeyPress, Qt::
Key_Left);
leftStopRight-&
gt;setTargetState(stopState);
KeyMoveTransition *
leftMoveRight =
new
KeyMoveTransition(this
, QEvent::
KeyPress, Qt::
Key_Left);
leftMoveRight-&
gt;setTargetState(moveStateRight);
KeyMoveTransition *
rightMoveRight =
new
KeyMoveTransition(this
, QEvent::
KeyPress, Qt::
Key_Right);
rightMoveRight-&
gt;setTargetState(moveStateRight);
KeyMoveTransition *
rightMoveStop =
new
KeyMoveTransition(this
, QEvent::
KeyPress, Qt::
Key_Right);
rightMoveStop-&
gt;setTargetState(moveStateRight);
//then setup the transitions for the leftMove state
KeyStopTransition *
rightStopLeft =
new
KeyStopTransition(this
, QEvent::
KeyPress, Qt::
Key_Right);
rightStopLeft-&
gt;setTargetState(stopState);
KeyMoveTransition *
rightMoveLeft =
new
KeyMoveTransition(this
, QEvent::
KeyPress, Qt::
Key_Right);
rightMoveLeft-&
gt;setTargetState(moveStateLeft);
KeyMoveTransition *
leftMoveLeft =
new
KeyMoveTransition(this
, QEvent::
KeyPress,Qt::
Key_Left);
leftMoveLeft-&
gt;setTargetState(moveStateLeft);
KeyMoveTransition *
leftMoveStop =
new
KeyMoveTransition(this
, QEvent::
KeyPress,Qt::
Key_Left);
leftMoveStop-&
gt;setTargetState(moveStateLeft);
//We set up the right move state
moveStateRight-&
gt;addTransition(leftStopRight);
moveStateRight-&
gt;addTransition(leftMoveRight);
moveStateRight-&
gt;addTransition(rightMoveRight);
stopState-&
gt;addTransition(rightMoveStop);
//We set up the left move state
moveStateLeft-&
gt;addTransition(rightStopLeft);
moveStateLeft-&
gt;addTransition(leftMoveLeft);
moveStateLeft-&
gt;addTransition(rightMoveLeft);
stopState-&
gt;addTransition(leftMoveStop);
//The animation is finished, it means we reached the border of the screen, the boat is stopped so we move to the stop state
moveStateLeft-&
gt;addTransition(movementAnimation, SIGNAL(finished()), stopState);
moveStateRight-&
gt;addTransition(movementAnimation, SIGNAL(finished()), stopState);
//We set up the keys for dropping bombs
KeyLaunchTransition *
upFireLeft =
new
KeyLaunchTransition(this
, QEvent::
KeyPress, Qt::
Key_Up);
upFireLeft-&
gt;setTargetState(launchStateRight);
KeyLaunchTransition *
upFireRight =
new
KeyLaunchTransition(this
, QEvent::
KeyPress, Qt::
Key_Up);
upFireRight-&
gt;setTargetState(launchStateRight);
KeyLaunchTransition *
upFireStop =
new
KeyLaunchTransition(this
, QEvent::
KeyPress, Qt::
Key_Up);
upFireStop-&
gt;setTargetState(launchStateRight);
KeyLaunchTransition *
downFireLeft =
new
KeyLaunchTransition(this
, QEvent::
KeyPress, Qt::
Key_Down);
downFireLeft-&
gt;setTargetState(launchStateLeft);
KeyLaunchTransition *
downFireRight =
new
KeyLaunchTransition(this
, QEvent::
KeyPress, Qt::
Key_Down);
downFireRight-&
gt;setTargetState(launchStateLeft);
KeyLaunchTransition *
downFireMove =
new
KeyLaunchTransition(this
, QEvent::
KeyPress, Qt::
Key_Down);
downFireMove-&
gt;setTargetState(launchStateLeft);
//We set up transitions for fire up
moveStateRight-&
gt;addTransition(upFireRight);
moveStateLeft-&
gt;addTransition(upFireLeft);
stopState-&
gt;addTransition(upFireStop);
//We set up transitions for fire down
moveStateRight-&
gt;addTransition(downFireRight);
moveStateLeft-&
gt;addTransition(downFireLeft);
stopState-&
gt;addTransition(downFireMove);
//Finally the launch state should come back to its original state
QHistoryState *
historyState =
new
QHistoryState(moving);
launchStateLeft-&
gt;addTransition(historyState);
launchStateRight-&
gt;addTransition(historyState);
QFinalState *
final
=
new
QFinalState(machine);
//This state play the destroyed animation
QAnimationState *
destroyedState =
new
QAnimationState(machine);
destroyedState-&
gt;setAnimation(destroyAnimation);
//Play a nice animation when the boat is destroyed
moving-&
gt;addTransition(this
, SIGNAL(boatDestroyed()), destroyedState);
//Transition to final state when the destroyed animation is finished
destroyedState-&
gt;addTransition(destroyedState, SIGNAL(animationFinished()), final
);
//The machine has finished to be executed, then the boat is dead
connect(machine,SIGNAL(finished()), this
, SIGNAL(boatExecutionFinished()));
}
void
Boat::
run()
{
//We register animations
AnimationManager::
self()-&
gt;registerAnimation(movementAnimation);
AnimationManager::
self()-&
gt;registerAnimation(destroyAnimation);
machine-&
gt;start();
}
void
Boat::
stop()
{
movementAnimation-&
gt;stop();
machine-&
gt;stop();
}
void
Boat::
updateBoatMovement()
{
if
(speed ==
0
||
direction ==
Boat::
None) {
movementAnimation-&
gt;stop();
return
;
}
movementAnimation-&
gt;stop();
if
(direction ==
Boat::
Left) {
movementAnimation-&
gt;setEndValue(QPointF(0
,y()));
movementAnimation-&
gt;setDuration(x()/
speed*
15
);
}
else
/*if (direction == Boat::Right)*/
{
movementAnimation-&
gt;setEndValue(QPointF(scene()-&
gt;width()-
size().width(),y()));
movementAnimation-&
gt;setDuration((scene()-&
gt;width()-
size().width()-
x())/
speed*
15
);
}
movementAnimation-&
gt;start();
}
void
Boat::
destroy()
{
movementAnimation-&
gt;stop();
emit boatDestroyed();
}
int
Boat::
bombsLaunched() const
{
return
bombsAlreadyLaunched;
}
void
Boat::
setBombsLaunched(int
number)
{
if
(number &
gt; MAX_BOMB) {
qWarning("Boat::setBombsLaunched : It impossible to launch that number of bombs"
);
return
;
}
bombsAlreadyLaunched =
number;
}
int
Boat::
currentSpeed() const
{
return
speed;
}
void
Boat::
setCurrentSpeed(int
speed)
{
if
(speed &
gt; 3
||
speed &
lt; 0
) {
qWarning("Boat::setCurrentSpeed: The boat can't run on that speed"
);
return
;
}
this
-&
gt;speed =
speed;
}
enum
Boat::
Movement Boat::
currentDirection() const
{
return
direction;
}
void
Boat::
setCurrentDirection(Movement direction)
{
this
-&
gt;direction =
direction;
}
int
Boat::
type() const
{
return
Type;
}