From ededfad305258f9f450b314d9e2d53a6905bc6d0 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Thu, 14 May 2009 13:12:12 +0200 Subject: Pop up message when a tank wins the game Also fixed: Added some docs and moved the tanks a little so they don't start partly outside the scene rect. --- doc/src/examples/tankgame.qdoc | 2 + .../statemachine/tankgame/gameovertransition.cpp | 39 ++++++++++++++++ .../statemachine/tankgame/gameovertransition.h | 22 +++++++++ examples/statemachine/tankgame/mainwindow.cpp | 53 ++++++++++++++++++---- examples/statemachine/tankgame/mainwindow.h | 3 ++ examples/statemachine/tankgame/tankgame.pro | 4 +- examples/statemachine/tankgame/tankitem.cpp | 1 + examples/statemachine/tankgame/tankitem.h | 1 + 8 files changed, 113 insertions(+), 12 deletions(-) create mode 100644 examples/statemachine/tankgame/gameovertransition.cpp create mode 100644 examples/statemachine/tankgame/gameovertransition.h diff --git a/doc/src/examples/tankgame.qdoc b/doc/src/examples/tankgame.qdoc index 1501a99..ab3e0f4 100644 --- a/doc/src/examples/tankgame.qdoc +++ b/doc/src/examples/tankgame.qdoc @@ -82,6 +82,8 @@ "Add tank" menu item should be disabled. This is implemented by giving the "stopped" state two children which define whether the map is full or not. + \snippet examples/statemachine/tankgame/mainwindow.cpp 5 + To make sure that we go into the correct child state when returning from the "running" state (if the "Stop game" menu item is selected while the game is running) we also give the "stopped" state a history state which we make the initial state of "stopped" state. 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 +#include + +GameOverTransition::GameOverTransition(QAbstractState *targetState) + : QSignalTransition(new QSignalMapper(), SIGNAL(mapped(QObject*))) +{ + setTargetState(targetState); + + QSignalMapper *mapper = qobject_cast(senderObject()); + mapper->setParent(this); +} + +void GameOverTransition::addTankItem(TankItem *tankItem) +{ + m_tankItems.append(tankItem); + + QSignalMapper *mapper = qobject_cast(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(e); + QObject *sender = qvariant_cast(signalEvent->arguments().at(0)); + TankItem *tankItem = qobject_cast(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 + +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 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 #include @@ -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 items = m_scene->items(); + + TankItem *lastTankStanding = 0; + foreach (QGraphicsItem *item, items) { + if (GameItem *gameItem = qgraphicsitem_cast(item)) { + if (lastTankStanding = qobject_cast(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(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 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); -- cgit v0.12