summaryrefslogtreecommitdiffstats
path: root/examples/statemachine
diff options
context:
space:
mode:
Diffstat (limited to 'examples/statemachine')
-rw-r--r--examples/statemachine/errorstate/tankitem.cpp5
-rw-r--r--examples/statemachine/errorstate/tankitem.h9
-rw-r--r--examples/statemachine/errorstateplugins/errorstateplugins.pro3
-rw-r--r--examples/statemachine/errorstateplugins/seek_ai/seek_ai.cpp42
-rw-r--r--examples/statemachine/errorstateplugins/seek_ai/seek_ai.h117
-rw-r--r--examples/statemachine/errorstateplugins/seek_ai/seek_ai.pro13
6 files changed, 184 insertions, 5 deletions
diff --git a/examples/statemachine/errorstate/tankitem.cpp b/examples/statemachine/errorstate/tankitem.cpp
index ae338fe..1e02171 100644
--- a/examples/statemachine/errorstate/tankitem.cpp
+++ b/examples/statemachine/errorstate/tankitem.cpp
@@ -141,6 +141,11 @@ void TankItem::turn(qreal degrees)
setAction(new TurnAction(this, degrees));
}
+void TankItem::turnTo(qreal degrees)
+{
+ setAction(new TurnAction(this, degrees - direction()));
+}
+
void TankItem::stop()
{
setAction(0);
diff --git a/examples/statemachine/errorstate/tankitem.h b/examples/statemachine/errorstate/tankitem.h
index 45016ec..cefed69 100644
--- a/examples/statemachine/errorstate/tankitem.h
+++ b/examples/statemachine/errorstate/tankitem.h
@@ -10,7 +10,7 @@ class TankItem: public GameItem
{
Q_OBJECT
Q_PROPERTY(bool enabled READ enabled WRITE setEnabled)
- Q_PROPERTY(qreal direction READ direction WRITE turn)
+ Q_PROPERTY(qreal direction READ direction WRITE turnTo)
Q_PROPERTY(qreal distanceToObstacle READ distanceToObstacle)
public:
TankItem(QObject *parent = 0);
@@ -42,9 +42,10 @@ signals:
void cannonFired();
public slots:
- void moveForwards(qreal length);
- void moveBackwards(qreal length);
- void turn(qreal newDirection);
+ void moveForwards(qreal length = 10.0);
+ void moveBackwards(qreal length = 10.0);
+ void turn(qreal degrees = 30.0);
+ void turnTo(qreal degrees = 0.0);
void stop();
void fireCannon();
diff --git a/examples/statemachine/errorstateplugins/errorstateplugins.pro b/examples/statemachine/errorstateplugins/errorstateplugins.pro
index e7718a9..5b6b758 100644
--- a/examples/statemachine/errorstateplugins/errorstateplugins.pro
+++ b/examples/statemachine/errorstateplugins/errorstateplugins.pro
@@ -1,7 +1,8 @@
TEMPLATE = subdirs
SUBDIRS = random_ai \
spin_ai_with_error \
- spin_ai
+ spin_ai \
+ seek_ai
# install
target.path = $$[QT_INSTALL_EXAMPLES]/statemachine/errorstateplugins
diff --git a/examples/statemachine/errorstateplugins/seek_ai/seek_ai.cpp b/examples/statemachine/errorstateplugins/seek_ai/seek_ai.cpp
new file mode 100644
index 0000000..229f83a
--- /dev/null
+++ b/examples/statemachine/errorstateplugins/seek_ai/seek_ai.cpp
@@ -0,0 +1,42 @@
+#include "seek_ai.h"
+
+QState *SeekAi::create(QState *parentState, QObject *tank)
+{
+ QState *topLevel = new QState(parentState);
+ topLevel->setObjectName("topLevel");
+
+ QState *seek = new QState(topLevel);
+ seek->setObjectName("seek");
+ topLevel->setInitialState(seek);
+
+ QState *lookForNearestWall = new SearchState(tank, seek);
+ lookForNearestWall->setObjectName("lookForNearestWall");
+ seek->setInitialState(lookForNearestWall);
+
+ QState *driveToFirstObstacle = new QState(seek);
+ driveToFirstObstacle->setObjectName("driveToFirstObstacle");
+ lookForNearestWall->addTransition(lookForNearestWall, SIGNAL(nearestObstacleStraightAhead()),
+ driveToFirstObstacle);
+
+ QState *drive = new QState(driveToFirstObstacle);
+ drive->setObjectName("drive");
+ driveToFirstObstacle->setInitialState(drive);
+ connect(drive, SIGNAL(entered()), tank, SLOT(moveForwards()));
+ connect(drive, SIGNAL(exited()), tank, SLOT(stop()));
+
+ // Go in loop
+ QState *finishedDriving = new QState(driveToFirstObstacle);
+ finishedDriving->setObjectName("finishedDriving");
+ drive->addTransition(tank, SIGNAL(actionCompleted()), finishedDriving);
+ finishedDriving->addTransition(drive);
+
+ QState *turnTo = new QState(seek);
+ turnTo->setObjectName("turnTo");
+ driveToFirstObstacle->addTransition(new CollisionTransition(tank, turnTo));
+
+ turnTo->addTransition(tank, SIGNAL(actionCompleted()), driveToFirstObstacle);
+
+ return topLevel;
+}
+
+Q_EXPORT_PLUGIN2(seek_ai, SeekAi)
diff --git a/examples/statemachine/errorstateplugins/seek_ai/seek_ai.h b/examples/statemachine/errorstateplugins/seek_ai/seek_ai.h
new file mode 100644
index 0000000..f96a68f
--- /dev/null
+++ b/examples/statemachine/errorstateplugins/seek_ai/seek_ai.h
@@ -0,0 +1,117 @@
+#ifndef SEEK_AI_H
+#define SEEK_AI_H
+
+#include <errorstate/plugin.h>
+
+#include <QState>
+#include <QSignalTransition>
+#include <QSignalEvent>
+#include <QVariant>
+#include <QLineF>
+
+class SearchState: public QState
+{
+ Q_OBJECT
+public:
+ SearchState(QObject *tank, QState *parentState = 0)
+ : QState(parentState),
+ m_tank(tank),
+ m_distanceToTurn(360.0),
+ m_nearestDistance(-1.0),
+ m_directionOfNearestObstacle(0.0)
+ {
+ }
+
+public slots:
+ void turnAlittle()
+ {
+ qreal dist = m_tank->property("distanceToObstacle").toDouble();
+
+ if (m_nearestDistance < 0.0 || dist < m_nearestDistance) {
+ m_nearestDistance = dist;
+ m_directionOfNearestObstacle = m_tank->property("direction").toDouble();
+ }
+
+ m_distanceToTurn -= 10.0;
+ if (m_distanceToTurn < 0.0) {
+ disconnect(m_tank, SIGNAL(actionCompleted()), this, SLOT(turnAlittle()));
+ connect(m_tank, SIGNAL(actionCompleted()), this, SIGNAL(nearestObstacleStraightAhead()));
+ m_tank->setProperty("direction", m_directionOfNearestObstacle);
+ }
+
+ qreal currentDirection = m_tank->property("direction").toDouble();
+ m_tank->setProperty("direction", currentDirection + 10.0);
+ }
+
+signals:
+ void nearestObstacleStraightAhead();
+
+protected:
+ void onEntry()
+ {
+ connect(m_tank, SIGNAL(actionCompleted()), this, SLOT(turnAlittle()));
+ turnAlittle();
+ }
+
+ void onExit()
+ {
+ disconnect(m_tank, SIGNAL(actionCompleted()), this, SLOT(turnAlittle()));
+ disconnect(m_tank, SIGNAL(actionCompleted()), this, SLOT(nearestObstacleStraightAhead()));
+ }
+
+private:
+ QObject *m_tank;
+
+ qreal m_distanceToTurn;
+ qreal m_nearestDistance;
+ qreal m_directionOfNearestObstacle;
+};
+
+class CollisionTransition: public QSignalTransition
+{
+public:
+ CollisionTransition(QObject *tank, QState *turnTo)
+ : QSignalTransition(tank, SIGNAL(collision(QLineF)), turnTo),
+ m_tank(tank),
+ m_turnTo(turnTo)
+ {
+ }
+
+protected:
+ bool eventTest(QEvent *event)
+ {
+ QSignalEvent *se = static_cast<QSignalEvent *>(event);
+ m_lastLine = se->arguments().at(0).toLineF();
+
+ return QSignalTransition::eventTest(event);
+ }
+
+ void onTransition()
+ {
+ qreal currentDirection = m_tank->property("direction").toDouble();
+ qreal angleOfWall = m_lastLine.angle();
+
+ qreal newDirection;
+ if (qAbs(currentDirection - angleOfWall) < qAbs(angleOfWall - currentDirection))
+ newDirection = angleOfWall;
+ else
+ newDirection = -angleOfWall;
+
+ m_turnTo->assignProperty(m_tank, "direction", newDirection);
+ }
+
+private:
+ QLineF m_lastLine;
+ QObject *m_tank;
+ QState *m_turnTo;
+};
+
+class SeekAi: public QObject, public Plugin
+{
+ Q_OBJECT
+ Q_INTERFACES(Plugin)
+public:
+ virtual QState *create(QState *parentState, QObject *tank);
+};
+
+#endif
diff --git a/examples/statemachine/errorstateplugins/seek_ai/seek_ai.pro b/examples/statemachine/errorstateplugins/seek_ai/seek_ai.pro
new file mode 100644
index 0000000..11bd242
--- /dev/null
+++ b/examples/statemachine/errorstateplugins/seek_ai/seek_ai.pro
@@ -0,0 +1,13 @@
+TEMPLATE = lib
+CONFIG += plugin
+INCLUDEPATH += ../..
+HEADERS = seek_ai.h
+SOURCES = seek_ai.cpp
+TARGET = $$qtLibraryTarget(seek_ai)
+DESTDIR = ../../errorstate/plugins
+
+#! [0]
+# install
+target.path = $$[QT_INSTALL_EXAMPLES]/statemachine/errorstate/plugins
+sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS seek_ai.pro
+sources.path = $$[QT_INSTALL_EXAMPLES]/statemachine/errorstateplugins/seek_ai \ No newline at end of file