From a9fd7d6881107b7e06362076c587530124fb1484 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Tue, 5 May 2009 16:38:53 +0200 Subject: Add chase state and ability to detect and fire at other tanks. This reveals an assert in the state machine which needs to be debugged. --- .../errorstateplugins/seek_ai/seek_ai.cpp | 6 ++ .../errorstateplugins/seek_ai/seek_ai.h | 90 +++++++++++++++++++++- 2 files changed, 92 insertions(+), 4 deletions(-) diff --git a/examples/statemachine/errorstateplugins/seek_ai/seek_ai.cpp b/examples/statemachine/errorstateplugins/seek_ai/seek_ai.cpp index 229f83a..2fb05d4 100644 --- a/examples/statemachine/errorstateplugins/seek_ai/seek_ai.cpp +++ b/examples/statemachine/errorstateplugins/seek_ai/seek_ai.cpp @@ -36,6 +36,12 @@ QState *SeekAi::create(QState *parentState, QObject *tank) turnTo->addTransition(tank, SIGNAL(actionCompleted()), driveToFirstObstacle); + ChaseState *chase = new ChaseState(tank, topLevel); + chase->setObjectName("chase"); + seek->addTransition(new TankSpottedTransition(tank, chase)); + chase->addTransition(chase, SIGNAL(finished()), driveToFirstObstacle); + chase->addTransition(new TankSpottedTransition(tank, chase)); + return topLevel; } diff --git a/examples/statemachine/errorstateplugins/seek_ai/seek_ai.h b/examples/statemachine/errorstateplugins/seek_ai/seek_ai.h index 7d8aa68..34d203e 100644 --- a/examples/statemachine/errorstateplugins/seek_ai/seek_ai.h +++ b/examples/statemachine/errorstateplugins/seek_ai/seek_ai.h @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -72,7 +73,7 @@ class CollisionTransition: public QSignalTransition { public: CollisionTransition(QObject *tank, QState *turnTo) - : QSignalTransition(tank, SIGNAL(collision(QLineF)), turnTo), + : QSignalTransition(tank, SIGNAL(collision(QLineF))), m_tank(tank), m_turnTo(turnTo) { @@ -82,16 +83,16 @@ public: protected: bool eventTest(QEvent *event) const { - if (event->type() == QEvent::Signal) { + bool b = QSignalTransition::eventTest(event); + if (b) { QSignalEvent *se = static_cast(event); m_lastLine = se->arguments().at(0).toLineF(); } - return QSignalTransition::eventTest(event); + return b; } void onTransition(QEvent *) { - qreal currentDirection = m_tank->property("direction").toDouble(); qreal angleOfWall = m_lastLine.angle(); qreal newDirection; @@ -109,6 +110,87 @@ private: QState *m_turnTo; }; +class ChaseState: public QState +{ + class GoToLocationState: public QState + { + public: + GoToLocationState(QObject *tank, QState *parentState = 0) + : QState(parentState), m_tank(tank), m_distance(0.0) + { + } + + void setDistance(qreal distance) { m_distance = distance; } + + protected: + void onEntry() + { + QMetaObject::invokeMethod(m_tank, "moveForwards", Q_ARG(qreal, m_distance)); + } + + private: + QObject *m_tank; + qreal m_distance; + }; + +public: + ChaseState(QObject *tank, QState *parentState = 0) : QState(parentState), m_tank(tank) + { + QState *fireCannon = new QState(this); + connect(fireCannon, SIGNAL(entered()), tank, SLOT(fireCannon())); + setInitialState(fireCannon); + + m_goToLocation = new GoToLocationState(this); + fireCannon->addTransition(tank, SIGNAL(actionCompleted()), m_goToLocation); + + m_turnToDirection = new QState(this); + m_goToLocation->addTransition(tank, SIGNAL(actionCompleted()), m_turnToDirection); + + QFinalState *finalState = new QFinalState(this); + m_turnToDirection->addTransition(tank, SIGNAL(actionCompleted()), finalState); + } + + void setDirection(qreal direction) + { + m_turnToDirection->assignProperty(m_tank, "direction", direction); + } + + void setDistance(qreal distance) + { + m_goToLocation->setDistance(distance); + } + +private: + QObject *m_tank; + GoToLocationState *m_goToLocation; + QState *m_turnToDirection; + +}; + +class TankSpottedTransition: public QSignalTransition +{ +public: + TankSpottedTransition(QObject *tank, ChaseState *target) : QSignalTransition(tank, SIGNAL(tankSpotted(qreal,qreal))), m_chase(target) + { + setTargetState(target); + } + +protected: + bool eventTest(QEvent *event) const + { + bool b = QSignalTransition::eventTest(event); + if (b) { + QSignalEvent *se = static_cast(event); + m_chase->setDirection(se->arguments().at(0).toDouble()); + m_chase->setDistance(se->arguments().at(1).toDouble()); + } + return b; + } + +private: + ChaseState *m_chase; +}; + class SeekAi: public QObject, public Plugin { Q_OBJECT -- cgit v0.12