summaryrefslogtreecommitdiffstats
path: root/examples/statemachine
diff options
context:
space:
mode:
Diffstat (limited to 'examples/statemachine')
-rw-r--r--examples/statemachine/tankgame/gameovertransition.cpp39
-rw-r--r--examples/statemachine/tankgame/gameovertransition.h22
-rw-r--r--examples/statemachine/tankgame/mainwindow.cpp53
-rw-r--r--examples/statemachine/tankgame/mainwindow.h3
-rw-r--r--examples/statemachine/tankgame/tankgame.pro4
-rw-r--r--examples/statemachine/tankgame/tankitem.cpp1
-rw-r--r--examples/statemachine/tankgame/tankitem.h1
7 files changed, 111 insertions, 12 deletions
diff --git a/examples/statemachine/tankgame/gameovertransition.cpp b/examples/statemachine/tankgame/gameovertransition.cpp
new file mode 100644
index 0000000..21c3510
--- /dev/null
+++ b/examples/statemachine/tankgame/gameovertransition.cpp
@@ -0,0 +1,39 @@
+#include "gameovertransition.h"
+#include "tankitem.h"
+
+#include <QSignalEvent>
+#include <QSignalMapper>
+
+GameOverTransition::GameOverTransition(QAbstractState *targetState)
+ : QSignalTransition(new QSignalMapper(), SIGNAL(mapped(QObject*)))
+{
+ setTargetState(targetState);
+
+ QSignalMapper *mapper = qobject_cast<QSignalMapper *>(senderObject());
+ mapper->setParent(this);
+}
+
+void GameOverTransition::addTankItem(TankItem *tankItem)
+{
+ m_tankItems.append(tankItem);
+
+ QSignalMapper *mapper = qobject_cast<QSignalMapper *>(senderObject());
+ mapper->setMapping(tankItem, tankItem);
+ connect(tankItem, SIGNAL(aboutToBeDestroyed()), mapper, SLOT(map()));
+}
+
+bool GameOverTransition::eventTest(QEvent *e) const
+{
+ bool ret = QSignalTransition::eventTest(e);
+
+ if (ret) {
+ QSignalEvent *signalEvent = static_cast<QSignalEvent *>(e);
+ QObject *sender = qvariant_cast<QObject *>(signalEvent->arguments().at(0));
+ TankItem *tankItem = qobject_cast<TankItem *>(sender);
+ m_tankItems.removeAll(tankItem);
+
+ return m_tankItems.size() <= 1;
+ } else {
+ return false;
+ }
+} \ No newline at end of file
diff --git a/examples/statemachine/tankgame/gameovertransition.h b/examples/statemachine/tankgame/gameovertransition.h
new file mode 100644
index 0000000..53c9b86
--- /dev/null
+++ b/examples/statemachine/tankgame/gameovertransition.h
@@ -0,0 +1,22 @@
+#ifndef GAMEOVERTRANSITION_H
+#define GAMEOVERTRANSITION_H
+
+#include <QSignalTransition>
+
+class TankItem;
+class GameOverTransition: public QSignalTransition
+{
+ Q_OBJECT
+public:
+ GameOverTransition(QAbstractState *targetState);
+
+ void addTankItem(TankItem *tankItem);
+
+protected:
+ bool eventTest(QEvent *event) const;
+
+private:
+ mutable QList<TankItem *> m_tankItems;
+};
+
+#endif
diff --git a/examples/statemachine/tankgame/mainwindow.cpp b/examples/statemachine/tankgame/mainwindow.cpp
index 870bc9c..fcc0325 100644
--- a/examples/statemachine/tankgame/mainwindow.cpp
+++ b/examples/statemachine/tankgame/mainwindow.cpp
@@ -2,6 +2,7 @@
#include "tankitem.h"
#include "rocketitem.h"
#include "plugin.h"
+#include "gameovertransition.h"
#include <QStateMachine>
#include <QGraphicsView>
@@ -53,7 +54,7 @@ void MainWindow::init()
{
TankItem *item = new TankItem(this);
- item->setPos(m_scene->sceneRect().topLeft() + QPointF(15.0, 15.0));
+ item->setPos(m_scene->sceneRect().topLeft() + QPointF(30.0, 30.0));
item->setDirection(45.0);
item->setColor(Qt::red);
@@ -63,7 +64,7 @@ void MainWindow::init()
{
TankItem *item = new TankItem(this);
- item->setPos(m_scene->sceneRect().topRight() + QPointF(-15.0, 15.0));
+ item->setPos(m_scene->sceneRect().topRight() + QPointF(-30.0, 30.0));
item->setDirection(135.0);
item->setColor(Qt::green);
@@ -73,7 +74,7 @@ void MainWindow::init()
{
TankItem *item = new TankItem(this);
- item->setPos(m_scene->sceneRect().bottomRight() + QPointF(-15.0, -15.0));
+ item->setPos(m_scene->sceneRect().bottomRight() + QPointF(-30.0, -30.0));
item->setDirection(225.0);
item->setColor(Qt::blue);
@@ -83,7 +84,7 @@ void MainWindow::init()
{
TankItem *item = new TankItem(this);
- item->setPos(m_scene->sceneRect().bottomLeft() + QPointF(15.0, -15.0));
+ item->setPos(m_scene->sceneRect().bottomLeft() + QPointF(30.0, -30.0));
item->setDirection(315.0);
item->setColor(Qt::yellow);
@@ -125,20 +126,23 @@ void MainWindow::init()
stoppedState->assignProperty(this, "started", false);
m_machine->setInitialState(stoppedState);
- QState *spawnsAvailable = new QState(stoppedState);
- spawnsAvailable->setObjectName("spawnsAvailable");
+//! [5]
+ QState *spawnsAvailable = new QState(stoppedState);
spawnsAvailable->assignProperty(addTankAction, "enabled", true);
- QState *noSpawnsAvailable = new QState(stoppedState);
- noSpawnsAvailable->setObjectName("noSpawnsAvailable");
+ QState *noSpawnsAvailable = new QState(stoppedState);
noSpawnsAvailable->assignProperty(addTankAction, "enabled", false);
+//! [5]
+ spawnsAvailable->setObjectName("spawnsAvailable");
+ noSpawnsAvailable->setObjectName("noSpawnsAvailable");
spawnsAvailable->addTransition(this, SIGNAL(mapFull()), noSpawnsAvailable);
//! [3]
- QHistoryState *hs = new QHistoryState(stoppedState);
+ QHistoryState *hs = new QHistoryState(stoppedState);
hs->setDefaultState(spawnsAvailable);
//! [3]
+ hs->setObjectName("hs");
stoppedState->setInitialState(hs);
@@ -149,10 +153,18 @@ void MainWindow::init()
m_runningState->assignProperty(addTankAction, "enabled", false);
m_runningState->assignProperty(runGameAction, "enabled", false);
m_runningState->assignProperty(stopGameAction, "enabled", true);
+
+ QState *gameOverState = new QState(m_machine->rootState());
+ gameOverState->setObjectName("gameOverState");
+ gameOverState->assignProperty(stopGameAction, "enabled", false);
+ connect(gameOverState, SIGNAL(entered()), this, SLOT(gameOver()));
stoppedState->addTransition(runGameAction, SIGNAL(triggered()), m_runningState);
m_runningState->addTransition(stopGameAction, SIGNAL(triggered()), stoppedState);
+ m_gameOverTransition = new GameOverTransition(gameOverState);
+ m_runningState->addTransition(m_gameOverTransition);
+
QTimer *timer = new QTimer(this);
timer->setInterval(100);
connect(timer, SIGNAL(timeout()), this, SLOT(runStep()));
@@ -182,6 +194,22 @@ void MainWindow::runStep()
}
}
+void MainWindow::gameOver()
+{
+ QList<QGraphicsItem *> items = m_scene->items();
+
+ TankItem *lastTankStanding = 0;
+ foreach (QGraphicsItem *item, items) {
+ if (GameItem *gameItem = qgraphicsitem_cast<GameItem *>(item)) {
+ if (lastTankStanding = qobject_cast<TankItem *>(gameItem))
+ break;
+ }
+ }
+
+ QMessageBox::information(this, "Game over!",
+ QString::fromLatin1("The tank played by '%1' has won!").arg(lastTankStanding->objectName()));
+}
+
void MainWindow::addRocket()
{
TankItem *tankItem = qobject_cast<TankItem *>(sender());
@@ -244,21 +272,26 @@ void MainWindow::addTank()
int idx = itemNames.indexOf(selectedName);
if (Plugin *plugin = idx >= 0 ? items.at(idx) : 0) {
TankItem *tankItem = m_spawns.takeLast();
+ tankItem->setObjectName(selectedName);
+ tankItem->setToolTip(selectedName);
m_scene->addItem(tankItem);
connect(tankItem, SIGNAL(cannonFired()), this, SLOT(addRocket()));
if (m_spawns.isEmpty())
emit mapFull();
+
+ m_gameOverTransition->addTankItem(tankItem);
QState *region = new QState(m_runningState);
+ region->setObjectName(QString::fromLatin1("region%1").arg(m_spawns.size()));
//! [2]
QState *pluginState = plugin->create(region, tankItem);
//! [2]
region->setInitialState(pluginState);
-
// If the plugin has an error it is disabled
//! [4]
QState *errorState = new QState(region);
+ errorState->setObjectName(QString::fromLatin1("errorState%1").arg(m_spawns.size()));
errorState->assignProperty(tankItem, "enabled", false);
pluginState->setErrorState(errorState);
//! [4]
diff --git a/examples/statemachine/tankgame/mainwindow.h b/examples/statemachine/tankgame/mainwindow.h
index 622dabe..40e1595 100644
--- a/examples/statemachine/tankgame/mainwindow.h
+++ b/examples/statemachine/tankgame/mainwindow.h
@@ -7,6 +7,7 @@
class QGraphicsScene;
class QStateMachine;
class QState;
+class GameOverTransition;
class TankItem;
class MainWindow: public QMainWindow
{
@@ -23,6 +24,7 @@ public slots:
void addTank();
void addRocket();
void runStep();
+ void gameOver();
signals:
void mapFull();
@@ -35,6 +37,7 @@ private:
QStateMachine *m_machine;
QState *m_runningState;
+ GameOverTransition *m_gameOverTransition;
QList<TankItem *> m_spawns;
QTime m_time;
diff --git a/examples/statemachine/tankgame/tankgame.pro b/examples/statemachine/tankgame/tankgame.pro
index f7b0760..46cfe2e 100644
--- a/examples/statemachine/tankgame/tankgame.pro
+++ b/examples/statemachine/tankgame/tankgame.pro
@@ -8,6 +8,6 @@ DEPENDPATH += .
INCLUDEPATH += C:/dev/kinetic/examples/statemachine/tankgame/. .
# Input
-HEADERS += mainwindow.h plugin.h tankitem.h rocketitem.h gameitem.h
-SOURCES += main.cpp mainwindow.cpp tankitem.cpp rocketitem.cpp gameitem.cpp
+HEADERS += mainwindow.h plugin.h tankitem.h rocketitem.h gameitem.h gameovertransition.h
+SOURCES += main.cpp mainwindow.cpp tankitem.cpp rocketitem.cpp gameitem.cpp gameovertransition.cpp
CONFIG += console
diff --git a/examples/statemachine/tankgame/tankitem.cpp b/examples/statemachine/tankgame/tankitem.cpp
index 5506a7e..c322d21 100644
--- a/examples/statemachine/tankgame/tankitem.cpp
+++ b/examples/statemachine/tankgame/tankitem.cpp
@@ -113,6 +113,7 @@ void TankItem::idle(qreal elapsed)
void TankItem::hitByRocket()
{
+ emit aboutToBeDestroyed();
deleteLater();
}
diff --git a/examples/statemachine/tankgame/tankitem.h b/examples/statemachine/tankgame/tankitem.h
index 66f05aa..9475397 100644
--- a/examples/statemachine/tankgame/tankitem.h
+++ b/examples/statemachine/tankgame/tankitem.h
@@ -41,6 +41,7 @@ signals:
void collision(const QLineF &collidedLine);
void actionCompleted();
void cannonFired();
+ void aboutToBeDestroyed();
public slots:
void moveForwards(qreal length = 10.0);