Qt 5.9 | Qt Widgets | Sub-Attaq | graphicsscene.cpp Example File

Qt 5.9.9 Reference Documentation

# graphicsscene.cpp Example File

animation/sub-attaq/graphicsscene.cpp

      /****************************************************************************
      **
      ** Copyright (C) 2016 The Qt Company Ltd.
      ** Contact: https://www.qt.io/licensing/
      **
      ** This file is part of the QtCore module of the Qt Toolkit.
      **
      ** $QT_BEGIN_LICENSE:BSD$
      ** Commercial License Usage
      ** Licensees holding valid commercial Qt licenses may use this file in
      ** accordance with the commercial license agreement provided with the
      ** Software or, alternatively, in accordance with the terms contained in
      ** a written agreement between you and The Qt Company. For licensing terms
      ** and conditions see https://www.qt.io/terms-conditions. For further
      ** information use the contact form at https://www.qt.io/contact-us.
      **
      ** BSD License Usage
      ** Alternatively, you may use this file under the terms of the BSD license
      ** as follows:
      **
      ** "Redistribution and use in source and binary forms, with or without
      ** modification, are permitted provided that the following conditions are
      ** met:
      **   * Redistributions of source code must retain the above copyright
      **     notice, this list of conditions and the following disclaimer.
      **   * Redistributions in binary form must reproduce the above copyright
      **     notice, this list of conditions and the following disclaimer in
      **     the documentation and/or other materials provided with the
      **     distribution.
      **   * Neither the name of The Qt Company Ltd nor the names of its
      **     contributors may be used to endorse or promote products derived
      **     from this software without specific prior written permission.
      **
      **
      ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
      ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
      ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
      ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
      ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
      ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
      ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
      ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
      **
      ** $QT_END_LICENSE$
      **
      ****************************************************************************/

      //Own
      #include "graphicsscene.h"
      #include "states.h"
      #include "boat.h"
      #include "submarine.h"
      #include "torpedo.h"
      #include "bomb.h"
      #include "pixmapitem.h"
      #include "animationmanager.h"
      #include "qanimationstate.h"
      #include "progressitem.h"
      #include "textinformationitem.h"

      //Qt
      #include <QtCore/QPropertyAnimation>
      #include <QtCore/QSequentialAnimationGroup>
      #include <QtCore/QParallelAnimationGroup>
      #include <QtCore/QStateMachine>
      #include <QtCore/QFinalState>
      #include <QtCore/QPauseAnimation>
      #include <QtWidgets/QAction>
      #include <QtCore/QDir>
      #include <QtWidgets/QApplication>
      #include <QtWidgets/QMessageBox>
      #include <QtWidgets/QGraphicsView>
      #include <QtWidgets/QGraphicsSceneMouseEvent>
      #include <QtCore/QXmlStreamReader>

      GraphicsScene::GraphicsScene(int x, int y, int width, int height, Mode mode)
          : QGraphicsScene(x , y, width, height), mode(mode), boat(new Boat)
      {
          PixmapItem *backgroundItem = new PixmapItem(QString("background"),mode);
          backgroundItem->setZValue(1);
          backgroundItem->setPos(0,0);
          addItem(backgroundItem);

          PixmapItem *surfaceItem = new PixmapItem(QString("surface"),mode);
          surfaceItem->setZValue(3);
          surfaceItem->setPos(0,sealLevel() - surfaceItem->boundingRect().height()/2);
          addItem(surfaceItem);

          //The item that display score and level
          progressItem = new ProgressItem(backgroundItem);

          textInformationItem = new TextInformationItem(backgroundItem);
          textInformationItem->hide();
          //We create the boat
          addItem(boat);
          boat->setPos(this->width()/2, sealLevel() - boat->size().height());
          boat->hide();

          //parse the xml that contain all data of the game
          QXmlStreamReader reader;
          QFile file(":data.xml");
          file.open(QIODevice::ReadOnly);
          reader.setDevice(&file);
          LevelDescription currentLevel;
          while (!reader.atEnd()) {
               reader.readNext();
               if (reader.tokenType() == QXmlStreamReader::StartElement) {
                   if (reader.name() == "submarine") {
                       SubmarineDescription desc;
                       desc.name = reader.attributes().value("name").toString();
                       desc.points = reader.attributes().value("points").toInt();
                       desc.type = reader.attributes().value("type").toInt();
                       submarinesData.append(desc);
                   } else if (reader.name() == "level") {
                       currentLevel.id = reader.attributes().value("id").toInt();
                       currentLevel.name = reader.attributes().value("name").toString();
                   } else if (reader.name() == "subinstance") {
                       currentLevel.submarines.append(qMakePair(reader.attributes().value("type").toInt(),
                                                                reader.attributes().value("nb").toInt()));
                   }
               } else if (reader.tokenType() == QXmlStreamReader::EndElement) {
                  if (reader.name() == "level") {
                      levelsData.insert(currentLevel.id, currentLevel);
                      currentLevel.submarines.clear();
                  }
               }
         }
      }

      qreal GraphicsScene::sealLevel() const
      {
          return (mode == Big) ? 220 : 160;
      }

      void GraphicsScene::setupScene(QAction *newAction, QAction *quitAction)
      {
          static const int nLetters = 10;
          static struct {
              char const *pix;
              qreal initX, initY;
              qreal destX, destY;
          } logoData[nLetters] = {
              {"s",   -1000, -1000, 300, 150 },
              {"u",    -800, -1000, 350, 150 },
              {"b",    -600, -1000, 400, 120 },
              {"dash", -400, -1000, 460, 150 },
              {"a",    1000,  2000, 350, 250 },
              {"t",     800,  2000, 400, 250 },
              {"t2",    600,  2000, 430, 250 },
              {"a2",    400,  2000, 465, 250 },
              {"q",     200,  2000, 510, 250 },
              {"excl",    0,  2000, 570, 220 } };

          QSequentialAnimationGroup * lettersGroupMoving = new QSequentialAnimationGroup(this);
          QParallelAnimationGroup * lettersGroupFading = new QParallelAnimationGroup(this);

          for (int i = 0; i < nLetters; ++i) {
              PixmapItem *logo = new PixmapItem(QLatin1String(":/logo-") + logoData[i].pix, this);
              logo->setPos(logoData[i].initX, logoData[i].initY);
              logo->setZValue(i + 3);
              //creation of the animations for moving letters
              QPropertyAnimation *moveAnim = new QPropertyAnimation(logo, "pos", lettersGroupMoving);
              moveAnim->setEndValue(QPointF(logoData[i].destX, logoData[i].destY));
              moveAnim->setDuration(200);
              moveAnim->setEasingCurve(QEasingCurve::OutElastic);
              lettersGroupMoving->addPause(50);
              //creation of the animations for fading out the letters
              QPropertyAnimation *fadeAnim = new QPropertyAnimation(logo, "opacity", lettersGroupFading);
              fadeAnim->setDuration(800);
              fadeAnim->setEndValue(0);
              fadeAnim->setEasingCurve(QEasingCurve::OutQuad);
          }

          QStateMachine *machine = new QStateMachine(this);

          //This state is when the player is playing
          PlayState *gameState = new PlayState(this, machine);

          //Final state
          QFinalState *final = new QFinalState(machine);

          //Animation when the player enter in the game
          QAnimationState *lettersMovingState = new QAnimationState(machine);
          lettersMovingState->setAnimation(lettersGroupMoving);

          //Animation when the welcome screen disappear
          QAnimationState *lettersFadingState = new QAnimationState(machine);
          lettersFadingState->setAnimation(lettersGroupFading);

          //if new game then we fade out the welcome screen and start playing
          lettersMovingState->addTransition(newAction, SIGNAL(triggered()), lettersFadingState);
          lettersFadingState->addTransition(lettersFadingState, SIGNAL(animationFinished()), gameState);

          //New Game is triggered then player start playing
          gameState->addTransition(newAction, SIGNAL(triggered()), gameState);

          //Wanna quit, then connect to CTRL+Q
          gameState->addTransition(quitAction, SIGNAL(triggered()), final);
          lettersMovingState->addTransition(quitAction, SIGNAL(triggered()), final);

          //Welcome screen is the initial state
          machine->setInitialState(lettersMovingState);

          machine->start();

          //We reach the final state, then we quit
          connect(machine, SIGNAL(finished()), qApp, SLOT(quit()));
      }

      void GraphicsScene::addItem(Bomb *bomb)
      {
          bombs.insert(bomb);
          connect(bomb,SIGNAL(bombExecutionFinished()),this, SLOT(onBombExecutionFinished()));
          QGraphicsScene::addItem(bomb);
      }

      void GraphicsScene::addItem(Torpedo *torpedo)
      {
          torpedos.insert(torpedo);
          connect(torpedo,SIGNAL(torpedoExecutionFinished()),this, SLOT(onTorpedoExecutionFinished()));
          QGraphicsScene::addItem(torpedo);
      }

      void GraphicsScene::addItem(SubMarine *submarine)
      {
          submarines.insert(submarine);
          connect(submarine,SIGNAL(subMarineExecutionFinished()),this, SLOT(onSubMarineExecutionFinished()));
          QGraphicsScene::addItem(submarine);
      }

      void GraphicsScene::addItem(QGraphicsItem *item)
      {
          QGraphicsScene::addItem(item);
      }

      void GraphicsScene::onBombExecutionFinished()
      {
          Bomb *bomb = qobject_cast<Bomb *>(sender());
          bombs.remove(bomb);
          bomb->deleteLater();
          if (boat)
              boat->setBombsLaunched(boat->bombsLaunched() - 1);
      }

      void GraphicsScene::onTorpedoExecutionFinished()
      {
          Torpedo *torpedo = qobject_cast<Torpedo *>(sender());
          torpedos.remove(torpedo);
          torpedo->deleteLater();
      }

      void GraphicsScene::onSubMarineExecutionFinished()
      {
          SubMarine *submarine = qobject_cast<SubMarine *>(sender());
          submarines.remove(submarine);
          if (submarines.count() == 0)
              emit allSubMarineDestroyed(submarine->points());
          else
              emit subMarineDestroyed(submarine->points());
          submarine->deleteLater();
      }

      void GraphicsScene::clearScene()
      {
          foreach (SubMarine *sub, submarines) {
              sub->destroy();
              sub->deleteLater();
          }

          foreach (Torpedo *torpedo, torpedos) {
              torpedo->destroy();
              torpedo->deleteLater();
          }

          foreach (Bomb *bomb, bombs) {
              bomb->destroy();
              bomb->deleteLater();
          }

          submarines.clear();
          bombs.clear();
          torpedos.clear();

          AnimationManager::self()->unregisterAllAnimations();

          boat->stop();
          boat->hide();
          boat->setEnabled(true);
      }