summaryrefslogtreecommitdiffstats
path: root/examples
diff options
context:
space:
mode:
Diffstat (limited to 'examples')
-rw-r--r--examples/statemachine/errorstate/gameitem.h5
-rw-r--r--examples/statemachine/errorstate/mainwindow.cpp19
-rw-r--r--examples/statemachine/errorstate/plugin.h2
-rw-r--r--examples/statemachine/errorstate/rocketitem.cpp9
-rw-r--r--examples/statemachine/errorstate/rocketitem.h5
-rw-r--r--examples/statemachine/errorstate/tankitem.cpp56
-rw-r--r--examples/statemachine/errorstate/tankitem.h10
-rw-r--r--examples/statemachine/errorstateplugins/errorstateplugins.pro10
-rw-r--r--examples/statemachine/errorstateplugins/spin_ai/spin_ai.cpp29
-rw-r--r--examples/statemachine/errorstateplugins/spin_ai/spin_ai.h44
-rw-r--r--examples/statemachine/errorstateplugins/spin_ai/spin_ai.pro13
-rw-r--r--examples/statemachine/errorstateplugins/spin_ai_with_error/spin_ai_with_error.cpp29
-rw-r--r--examples/statemachine/errorstateplugins/spin_ai_with_error/spin_ai_with_error.h44
-rw-r--r--examples/statemachine/errorstateplugins/spin_ai_with_error/spin_ai_with_error.pro13
14 files changed, 262 insertions, 26 deletions
diff --git a/examples/statemachine/errorstate/gameitem.h b/examples/statemachine/errorstate/gameitem.h
index 6ca32b7..9808706 100644
--- a/examples/statemachine/errorstate/gameitem.h
+++ b/examples/statemachine/errorstate/gameitem.h
@@ -7,13 +7,8 @@ class QLineF;
class GameItem: public QGraphicsItem
{
public:
- enum { Type = UserType + 1 };
-
- int type() const { return Type; }
virtual void idle(qreal elapsed) = 0;
- virtual void hitByRocket() = 0;
-
protected:
QPointF tryMove(const QPointF &requestedPosition, QLineF *collidedLine = 0,
QGraphicsItem **collidedItem = 0) const;
diff --git a/examples/statemachine/errorstate/mainwindow.cpp b/examples/statemachine/errorstate/mainwindow.cpp
index e04ca94..daf7be0 100644
--- a/examples/statemachine/errorstate/mainwindow.cpp
+++ b/examples/statemachine/errorstate/mainwindow.cpp
@@ -105,6 +105,7 @@ void MainWindow::init()
QAction *addTankAction = menuBar()->addAction("&Add tank");
QAction *runGameAction = menuBar()->addAction("&Run game");
+ runGameAction->setObjectName("runGameAction");
QAction *stopGameAction = menuBar()->addAction("&Stop game");
menuBar()->addSeparator();
QAction *quitAction = menuBar()->addAction("&Quit");
@@ -112,9 +113,7 @@ void MainWindow::init()
connect(addTankAction, SIGNAL(triggered()), this, SLOT(addTank()));
connect(quitAction, SIGNAL(triggered()), this, SLOT(close()));
- m_machine = new QStateMachine(this);
- m_machine->setGlobalRestorePolicy(QStateMachine::RestoreProperties);
-
+ m_machine = new QStateMachine(this);
QState *stoppedState = new QState(m_machine->rootState());
stoppedState->setObjectName("stoppedState");
stoppedState->assignProperty(runGameAction, "enabled", true);
@@ -168,7 +167,11 @@ void MainWindow::runStep()
qreal elapsedSecs = elapsed / 1000.0;
QList<QGraphicsItem *> items = m_scene->items();
foreach (QGraphicsItem *item, items) {
- GameItem *gameItem = qgraphicsitem_cast<GameItem *>(item);
+ // ###
+ GameItem *gameItem = qgraphicsitem_cast<TankItem *>(item);
+ if (gameItem == 0)
+ gameItem = qgraphicsitem_cast<RocketItem *>(item);
+
if (gameItem != 0)
gameItem->idle(elapsedSecs);
}
@@ -206,7 +209,13 @@ void MainWindow::addTank()
emit mapFull();
QState *region = new QState(m_runningState);
- region->setInitialState(plugin->create(region, tankItem));
+ QState *pluginState = plugin->create(region, tankItem);
+ region->setInitialState(pluginState);
+
+ // If the plugin has an error it is disabled
+ QState *errorState = new QState(region);
+ errorState->assignProperty(tankItem, "enabled", false);
+ pluginState->setErrorState(errorState);
}
}
diff --git a/examples/statemachine/errorstate/plugin.h b/examples/statemachine/errorstate/plugin.h
index 1ac7e0f..69b9574 100644
--- a/examples/statemachine/errorstate/plugin.h
+++ b/examples/statemachine/errorstate/plugin.h
@@ -1,6 +1,8 @@
#ifndef PLUGIN_H
#define PLUGIN_H
+#include <QtPlugin>
+
class QState;
class Tank;
class Plugin
diff --git a/examples/statemachine/errorstate/rocketitem.cpp b/examples/statemachine/errorstate/rocketitem.cpp
index de9eef7..85d436b 100644
--- a/examples/statemachine/errorstate/rocketitem.cpp
+++ b/examples/statemachine/errorstate/rocketitem.cpp
@@ -1,4 +1,5 @@
#include "rocketitem.h"
+#include "tankitem.h"
#include <QPainter>
#include <QGraphicsScene>
@@ -25,10 +26,6 @@ void RocketItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWid
painter->drawEllipse(boundingRect());
}
-void RocketItem::hitByRocket()
-{
-}
-
void RocketItem::idle(qreal elapsed)
{
qreal dist = elapsed * speed();
@@ -51,8 +48,8 @@ void RocketItem::idle(qreal elapsed)
if (requestedPosition == nextPosition) {
setPos(nextPosition);
} else {
- if (GameItem *gameItem = qgraphicsitem_cast<GameItem *>(collidedItem))
- gameItem->hitByRocket();
+ if (TankItem *tankItem = qgraphicsitem_cast<TankItem *>(collidedItem))
+ tankItem->hitByRocket();
scene()->removeItem(this);
delete this;
diff --git a/examples/statemachine/errorstate/rocketitem.h b/examples/statemachine/errorstate/rocketitem.h
index 9805a8a..b055b0a 100644
--- a/examples/statemachine/errorstate/rocketitem.h
+++ b/examples/statemachine/errorstate/rocketitem.h
@@ -6,13 +6,14 @@
class RocketItem: public GameItem
{
public:
+ enum { Type = UserType + 2 };
+
RocketItem();
+ int type() const { return Type; }
virtual void idle(qreal elapsed);
qreal speed() const { return 100.0; }
void setDirection(qreal direction) { m_direction = direction; }
-
- void hitByRocket();
protected:
virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
diff --git a/examples/statemachine/errorstate/tankitem.cpp b/examples/statemachine/errorstate/tankitem.cpp
index 814de2b..705623c 100644
--- a/examples/statemachine/errorstate/tankitem.cpp
+++ b/examples/statemachine/errorstate/tankitem.cpp
@@ -85,17 +85,25 @@ private:
bool m_reverse;
};
-TankItem::TankItem(QObject *parent) : Tank(parent), m_currentAction(0), m_currentDirection(0.0)
+TankItem::TankItem(QObject *parent)
+ : Tank(parent), m_currentAction(0), m_currentDirection(0.0), m_enabled(true)
{
connect(this, SIGNAL(fireCannon()), this, SIGNAL(actionCompleted()));
}
void TankItem::idle(qreal elapsed)
{
- if (m_currentAction != 0) {
- if (!m_currentAction->apply(elapsed)) {
- setAction(0);
- emit actionCompleted();
+ if (m_enabled) {
+ if (m_currentAction != 0) {
+ if (!m_currentAction->apply(elapsed)) {
+ setAction(0);
+ emit actionCompleted();
+ }
+
+ QGraphicsItem *item = 0;
+ qreal distance = distanceToObstacle(&item);
+ if (TankItem *tankItem = qgraphicsitem_cast<TankItem *>(item))
+ emit tankSpotted(tankItem->direction(), distance);
}
}
}
@@ -176,6 +184,17 @@ void TankItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidge
QPointF(brect.right() - 2.0, brect.bottom()));
painter->fillRect(rightTrackRect, Qt::darkYellow);
painter->drawRect(rightTrackRect);
+
+ if (!m_enabled) {
+ painter->setPen(QPen(Qt::red, 5));
+
+ painter->drawEllipse(brect);
+
+ QPainterPath path;
+ path.addEllipse(brect);
+ painter->setClipPath(path);
+ painter->drawLine(brect.topRight(), brect.bottomLeft());
+ }
}
QRectF TankItem::boundingRect() const
@@ -195,11 +214,32 @@ void TankItem::setDirection(qreal newDirection)
rotate(diff);
}
-qreal TankItem::distanceToObstacle() const
+qreal TankItem::distanceToObstacle(QGraphicsItem **obstacle) const
{
- // ###
+ qreal dist = sqrt(pow(scene()->sceneRect().width(), 2) + pow(scene()->sceneRect().height(), 2));
+
+ qreal a = m_currentDirection * M_PI / 180.0;
+
+ qreal yd = dist * sin(a);
+ qreal xd = dist * sin(M_PI / 2.0 - a);
- return 0.0;
+ QPointF requestedPosition = pos() + QPointF(xd, yd);
+ QGraphicsItem *collidedItem = 0;
+ QPointF nextPosition = tryMove(requestedPosition, 0, &collidedItem);
+ if (collidedItem != 0) {
+ if (obstacle != 0)
+ *obstacle = collidedItem;
+
+ QPointF d = nextPosition - pos();
+ return sqrt(pow(d.x(), 2) + pow(d.y(), 2));
+ } else {
+ return 0.0;
+ }
+}
+
+qreal TankItem::distanceToObstacle() const
+{
+ return distanceToObstacle(0);
}
diff --git a/examples/statemachine/errorstate/tankitem.h b/examples/statemachine/errorstate/tankitem.h
index c9e0d22..e598cfd 100644
--- a/examples/statemachine/errorstate/tankitem.h
+++ b/examples/statemachine/errorstate/tankitem.h
@@ -10,8 +10,13 @@ class Action;
class TankItem: public Tank, public GameItem
{
Q_OBJECT
+ Q_PROPERTY(bool enabled READ enabled WRITE setEnabled)
public:
+ enum { Type = UserType + 1 };
+
TankItem(QObject *parent = 0);
+
+ int type() const { return Type; }
virtual void moveForwards(qreal length);
virtual void moveBackwards(qreal length);
@@ -19,6 +24,7 @@ public:
virtual void stop();
virtual qreal direction() const;
virtual qreal distanceToObstacle() const;
+ virtual qreal distanceToObstacle(QGraphicsItem **item) const;
void setColor(const QColor &color) { m_color = color; }
QColor color() const { return m_color; }
@@ -33,6 +39,9 @@ public:
void hitByRocket();
+ void setEnabled(bool b) { m_enabled = b; }
+ bool enabled() const { return m_enabled; }
+
signals:
virtual void fireCannon();
@@ -46,6 +55,7 @@ private:
Action *m_currentAction;
qreal m_currentDirection;
QColor m_color;
+ bool m_enabled;
};
#endif
diff --git a/examples/statemachine/errorstateplugins/errorstateplugins.pro b/examples/statemachine/errorstateplugins/errorstateplugins.pro
new file mode 100644
index 0000000..e7718a9
--- /dev/null
+++ b/examples/statemachine/errorstateplugins/errorstateplugins.pro
@@ -0,0 +1,10 @@
+TEMPLATE = subdirs
+SUBDIRS = random_ai \
+ spin_ai_with_error \
+ spin_ai
+
+# install
+target.path = $$[QT_INSTALL_EXAMPLES]/statemachine/errorstateplugins
+sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS errorstateplugins.pro
+sources.path = $$[QT_INSTALL_EXAMPLES]/statemachine/errorstateplugins
+INSTALLS += target sources
diff --git a/examples/statemachine/errorstateplugins/spin_ai/spin_ai.cpp b/examples/statemachine/errorstateplugins/spin_ai/spin_ai.cpp
new file mode 100644
index 0000000..8452523
--- /dev/null
+++ b/examples/statemachine/errorstateplugins/spin_ai/spin_ai.cpp
@@ -0,0 +1,29 @@
+#include "spin_ai.h"
+
+#include <QtPlugin>
+
+QState *SpinAi::create(QState *parentState, Tank *tank)
+{
+ QState *topLevel = new QState(parentState);
+ QState *spinState = new SpinState(tank, topLevel);
+ topLevel->setInitialState(spinState);
+
+ // When tank is spotted, fire two times and go back to spin state
+ QState *fireState = new QState(topLevel);
+
+ QState *fireOnce = new QState(fireState);
+ fireState->setInitialState(fireOnce);
+ connect(fireOnce, SIGNAL(entered()), tank, SLOT(fireCannon()));
+
+ QState *fireTwice = new QState(fireState);
+ connect(fireTwice, SIGNAL(entered()), tank, SLOT(fireCannon()));
+
+ fireOnce->addTransition(tank, SIGNAL(actionCompleted()), fireTwice);
+ fireTwice->addTransition(tank, SIGNAL(actionCompleted()), spinState);
+
+ spinState->addTransition(tank, SIGNAL(tankSpotted(qreal,qreal)), fireState);
+
+ return topLevel;
+}
+
+Q_EXPORT_PLUGIN2(spin_ai, SpinAi)
diff --git a/examples/statemachine/errorstateplugins/spin_ai/spin_ai.h b/examples/statemachine/errorstateplugins/spin_ai/spin_ai.h
new file mode 100644
index 0000000..7336640
--- /dev/null
+++ b/examples/statemachine/errorstateplugins/spin_ai/spin_ai.h
@@ -0,0 +1,44 @@
+#ifndef SPIN_AI_H
+#define SPIN_AI_H
+
+#include <errorstate/plugin.h>
+#include <errorstate/tank.h>
+
+#include <QObject>
+#include <QState>
+
+class SpinState: public QState
+{
+ Q_OBJECT
+public:
+ SpinState(Tank *tank, QState *parent) : QState(parent), m_tank(tank)
+ {
+ }
+
+public slots:
+ void spin()
+ {
+ m_tank->turn(90.0);
+ }
+
+protected:
+ void onEntry()
+ {
+ connect(m_tank, SIGNAL(actionCompleted()), this, SLOT(spin()));
+ spin();
+ }
+
+private:
+ Tank *m_tank;
+
+};
+
+class SpinAi: public QObject, public Plugin
+{
+ Q_OBJECT
+ Q_INTERFACES(Plugin)
+public:
+ virtual QState *create(QState *parentState, Tank *tank);
+};
+
+#endif
diff --git a/examples/statemachine/errorstateplugins/spin_ai/spin_ai.pro b/examples/statemachine/errorstateplugins/spin_ai/spin_ai.pro
new file mode 100644
index 0000000..c2fd937
--- /dev/null
+++ b/examples/statemachine/errorstateplugins/spin_ai/spin_ai.pro
@@ -0,0 +1,13 @@
+TEMPLATE = lib
+CONFIG += plugin
+INCLUDEPATH += ../..
+HEADERS = spin_ai.h
+SOURCES = spin_ai.cpp
+TARGET = $$qtLibraryTarget(spin_ai)
+DESTDIR = ../../errorstate/plugins
+
+#! [0]
+# install
+target.path = $$[QT_INSTALL_EXAMPLES]/statemachine/errorstate/plugins
+sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS spin_ai.pro
+sources.path = $$[QT_INSTALL_EXAMPLES]/statemachine/errorstateplugins/spin_ai \ No newline at end of file
diff --git a/examples/statemachine/errorstateplugins/spin_ai_with_error/spin_ai_with_error.cpp b/examples/statemachine/errorstateplugins/spin_ai_with_error/spin_ai_with_error.cpp
new file mode 100644
index 0000000..dd73270
--- /dev/null
+++ b/examples/statemachine/errorstateplugins/spin_ai_with_error/spin_ai_with_error.cpp
@@ -0,0 +1,29 @@
+#include "spin_ai_with_error.h"
+
+#include <QtPlugin>
+
+QState *SpinAiWithError::create(QState *parentState, Tank *tank)
+{
+ QState *topLevel = new QState(parentState);
+ QState *spinState = new SpinState(tank, topLevel);
+ topLevel->setInitialState(spinState);
+
+ // When tank is spotted, fire two times and go back to spin state
+ // (no initial state set for fireState will lead to run-time error in machine)
+ QState *fireState = new QState(topLevel);
+
+ QState *fireOnce = new QState(fireState);
+ connect(fireOnce, SIGNAL(entered()), tank, SLOT(fireCannon()));
+
+ QState *fireTwice = new QState(fireState);
+ connect(fireTwice, SIGNAL(entered()), tank, SLOT(fireCannon()));
+
+ fireOnce->addTransition(tank, SIGNAL(actionCompleted()), fireTwice);
+ fireTwice->addTransition(tank, SIGNAL(actionCompleted()), spinState);
+
+ spinState->addTransition(tank, SIGNAL(tankSpotted(qreal,qreal)), fireState);
+
+ return topLevel;
+}
+
+Q_EXPORT_PLUGIN2(spin_ai_with_error, SpinAiWithError)
diff --git a/examples/statemachine/errorstateplugins/spin_ai_with_error/spin_ai_with_error.h b/examples/statemachine/errorstateplugins/spin_ai_with_error/spin_ai_with_error.h
new file mode 100644
index 0000000..26def66
--- /dev/null
+++ b/examples/statemachine/errorstateplugins/spin_ai_with_error/spin_ai_with_error.h
@@ -0,0 +1,44 @@
+#ifndef SPIN_AI_WITH_ERROR_H
+#define SPIN_AI_WITH_ERROR_H
+
+#include <errorstate/plugin.h>
+#include <errorstate/tank.h>
+
+#include <QObject>
+#include <QState>
+
+class SpinState: public QState
+{
+ Q_OBJECT
+public:
+ SpinState(Tank *tank, QState *parent) : QState(parent), m_tank(tank)
+ {
+ }
+
+public slots:
+ void spin()
+ {
+ m_tank->turn(90.0);
+ }
+
+protected:
+ void onEntry()
+ {
+ connect(m_tank, SIGNAL(actionCompleted()), this, SLOT(spin()));
+ spin();
+ }
+
+private:
+ Tank *m_tank;
+
+};
+
+class SpinAiWithError: public QObject, public Plugin
+{
+ Q_OBJECT
+ Q_INTERFACES(Plugin)
+public:
+ virtual QState *create(QState *parentState, Tank *tank);
+};
+
+#endif
diff --git a/examples/statemachine/errorstateplugins/spin_ai_with_error/spin_ai_with_error.pro b/examples/statemachine/errorstateplugins/spin_ai_with_error/spin_ai_with_error.pro
new file mode 100644
index 0000000..31f4c7f
--- /dev/null
+++ b/examples/statemachine/errorstateplugins/spin_ai_with_error/spin_ai_with_error.pro
@@ -0,0 +1,13 @@
+TEMPLATE = lib
+CONFIG += plugin
+INCLUDEPATH += ../..
+HEADERS = spin_ai_with_error.h
+SOURCES = spin_ai_with_error.cpp
+TARGET = $$qtLibraryTarget(spin_ai_with_error)
+DESTDIR = ../../errorstate/plugins
+
+#! [0]
+# install
+target.path = $$[QT_INSTALL_EXAMPLES]/statemachine/errorstate/plugins
+sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS spin_ai_with_error.pro
+sources.path = $$[QT_INSTALL_EXAMPLES]/statemachine/errorstateplugins/spin_ai_with_error \ No newline at end of file