File indexing completed on 2024-04-21 04:04:45

0001 /* This file is part of KsirK.
0002    Copyright (C) 2001-2007 Gael de Chalendar <kleag@free.fr>
0003 
0004    KsirK is free software; you can redistribute it and/or
0005    modify it under the terms of the GNU General Public
0006    License as published by the Free Software Foundation, either version 2
0007    of the License, or (at your option) any later version.
0008 
0009    This program is distributed in the hope that it will be useful,
0010    but WITHOUT ANY WARRANTY; without even the implied warranty of
0011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0012    General Public License for more details.
0013 
0014    You should have received a copy of the GNU General Public License
0015    along with this program; if not, write to the Free Software
0016    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
0017    02110-1301, USA
0018 */
0019 
0020 /*  begin                : Wed Jul 18 2001  */
0021 
0022 
0023 #ifndef ANIMSPRITE_H
0024 #define ANIMSPRITE_H
0025 
0026 #include "KsirkGlobalDefinitions.h"
0027 #include "animspritespool.h"
0028 
0029 #include <QGraphicsItem>
0030 #include <QPixmap>
0031 #include <QTimer>
0032 
0033 #include <limits>
0034 #include <QTextStream>
0035 
0036 class QSvgRenderer;
0037 
0038 namespace Ksirk
0039 {
0040 
0041 class BackGnd;
0042 namespace GameLogic
0043 {
0044   class Country;
0045 }
0046 
0047 /**
0048  * The AnimSprite objects are the animated images used for all individual
0049  * moving objects in KsirK. It is based on QGraphicsPixmapItem that handle
0050  * all sprite specific behavior (sequence of images...). The individual
0051  * images are taken from an SVG image that stores all the versions of the sprite.
0052  * A sprite also have a direction (that allows to select the images looking
0053  * toward left or right) and a destination point allowing to handle sprite
0054  * movement.
0055  *
0056  */
0057 class AnimSprite : public QObject, public QGraphicsPixmapItem
0058 {
0059   Q_OBJECT
0060 public:
0061   /**
0062   * When used for fight display, the sprites can be attacker or
0063   * defendant. In the other cases, they are nothing particular (NONE)
0064   * This state is only used for explosion animation
0065   */
0066   enum State {NONE, ATTACKER, DEFENDANT};
0067 
0068   enum TDir {state, right, left, up, down, N, S, E, O, NO, SO, SE, NE};
0069 
0070   /**
0071     * This constructor allows to create a new @ref AnimSprite whose images are
0072     * taken from the given file name with the given number of frames and
0073     * number of look directions
0074     * @param svgid The id of the SVG element from which to load images
0075     * @param aBackGnd The background giving info about the world geometry and
0076     * access to the underlying QGraphicsScene
0077     * @param nbFrames The number of different frames in this sprite animation, 
0078     * thus the number of columns in the sprite image
0079     * @param nbDirs The number of different views on the sprite, 
0080     * thus the number of rows in the sprite image
0081     * @param visibility Measures how much this sprite is visible. It gives its
0082     * Z value on the graphics scene.
0083     */
0084   AnimSprite(const QString &svgid,
0085               unsigned int width,
0086               unsigned int height,
0087               unsigned int nbFrames, unsigned int nbDirs,
0088               double zoom,
0089               BackGnd* aBackGnd,
0090               unsigned int visibility = 100);
0091 
0092   /** The default destructor */
0093   ~AnimSprite() override;
0094 
0095   /**
0096     * Moves the sprite by one step towards its destinationPoint.
0097     */
0098   void moveIt();
0099 
0100   /**
0101     * Hides and shows the sprite. Causes it to be repainted.
0102     */
0103   void repaint();
0104 
0105   /**
0106     * Return true if the current frame is the last one. False otherwise.
0107     */
0108   bool isLastFrame() const;
0109 
0110   //@{
0111   /**
0112     * Accessors to some variables
0113     */
0114   void setDestination(GameLogic::Country *);
0115   GameLogic::Country *getDestination();
0116   void setDestinationPoint(const QPointF &);
0117   const QPointF& getDestinationPoint() const;
0118   bool isAttacker() const;
0119   void setAttacker();
0120   bool isDefendant() const;
0121   void setDefendant();
0122   bool isNone() const;
0123   void setNone();
0124   inline BackGnd* getBackGnd() {return backGnd;}
0125   //@}
0126 
0127   /**
0128     * Bit to bit comparison
0129     */
0130   int operator==(const AnimSprite& Arg1) const;
0131 
0132   /**
0133     * executes setLook towards left or right according to the relative
0134     * abscissa of the current position point and the destination point
0135     */
0136   void turnTowardDestination();
0137 
0138   /**
0139     * Simplified changing of the images sequence of the sprite. Use default
0140     * values built from the given id
0141     * @param id The base id from which skin data is accessed
0142     */
0143   void changeSequence(const QString &id);
0144 
0145   /**
0146     * Change the images sequence of the sprite.
0147     * @param imgPath The path to the SVG file containing the sprite's new images
0148     * @param newNbFrames The number of frames of the sprite in the new image
0149     * @param nbDirs The number of directions of the sprite in the new image
0150     */
0151   void changeSequence(const QString &imgPath,
0152                        unsigned int width,
0153                        unsigned int height,
0154                        unsigned int newNbFrames, unsigned int nbDirs);
0155 
0156   /** Turns the sprite towards left */
0157   void setLookLeft();
0158 
0159   /** Turns the sprite towards right */
0160   void setLookRight();
0161 
0162   /** 
0163     * Test if the sprites looks to left
0164     * @return true if the sprite is directed towards left and false otherwise 
0165     */
0166   bool looksToLeft() const;
0167 
0168   /** 
0169     * Test if the sprites looks to right
0170     * @return true if the sprite is directed towards right and true otherwise 
0171     */
0172   bool looksToRight() const;
0173 
0174   /** Write property of bool approachDestByRight. */
0175   void setApproachDestByRight( const bool& _newVal);
0176   /** Read property of bool approachDestByRight. */
0177   bool getApproachDestByRight() const;
0178 
0179   /** Write property of bool approachDestByLeft . */
0180   void setApproachDestByLeft ( const bool& _newVal);
0181   /** Read property of bool approachDestByLeft . */
0182   bool getApproachDestByLeft () const;
0183 
0184   /** Write property of bool approachDestByTop. */
0185   void setApproachDestByTop( const bool& _newVal);
0186   /** Read property of bool approachDestByTop. */
0187   bool getApproachDestByTop() const;
0188 
0189   /** Write property of bool approachDestByBottom . */
0190   void setApproachDestByBottom ( const bool& _newVal);
0191   /** Read property of bool approachDestByBottom . */
0192   bool getApproachDestByBottom () const;
0193 
0194   /** 
0195     * Return the maximum value for x for this sprite by looking to its 
0196     * including background. Necessary for directed approaches. 
0197     */
0198   qreal getMaxX() const;
0199 
0200   /** 
0201     * Return the maximum value for y for this sprite by looking to its 
0202     * including background. Necessary for directed approaches. 
0203     */
0204   qreal getMaxY() const;
0205 
0206   /** returns the current state of the sprite */
0207   State getState() const;
0208 
0209   /** Return true if the state of the game is the argument; false otherwise */
0210   bool isMyState(State state) const;
0211 
0212   /** sets the new state of the game */
0213   void setState(State newState);
0214 
0215   /**
0216     * This function chooses the approach mode of a sprite towards its destination:
0217     * if the distance between the origin and the destination is higher than half
0218     * the size of the map and if the origin and destination countries comunicate,
0219     * then the sprite should choose an approach by left or right, through the
0220     * edge of the map.
0221     * This protected method will be called by three public functions specialized
0222     * using as source point, respectivly, the infantryman point, the cavalryman
0223     * point and the cannon point.
0224     */
0225   void setupTravel(GameLogic::Country* src, GameLogic::Country* dest, 
0226     const QPointF& srcPoint, const QPointF& destPoint);
0227 
0228   /**
0229     * This virtual function chooses the approach mode of a sprite towards its
0230     * destination. It will be overloaded by subclasses:
0231     * if the distance between the origin and the destination is higher than half
0232     * the size of the map and if the origin and destination countries comunicate,
0233     * then the sprite should choose an approach by left or right, through the
0234     * edge of the map.
0235     */
0236   virtual void setupTravel(GameLogic::Country* src, GameLogic::Country* dest, 
0237     const QPointF* dpi=nullptr);
0238 
0239   /**
0240     * Saves a XML representation of the sprite for game saving purpose
0241     * @param xmlStream The stream to write on
0242     */
0243   virtual void saveXml(QTextStream& xmlStream);
0244   
0245   /**
0246     * Retrieves the numFrame's frame image of this sprite in its current 
0247     * direction
0248     * @param numFrame The index of the image to retrieve
0249     * @return a copy of the numFrame's image of this sprite in its current 
0250     * direction
0251     */
0252   QPixmap image(unsigned int numFrame) const;
0253 
0254   void arrival();
0255 
0256   void setAnimated(unsigned int numberOfShots = std::numeric_limits<unsigned int>::max());
0257 
0258   void setStatic();
0259 
0260   void applyZoomFactor(qreal zoomFactor);
0261 
0262   void addDecoration(const QString& svgid, const QRectF& geometry);
0263   
0264 public slots:
0265   void animate();
0266 
0267 signals:
0268 
0269   /**
0270     * emitted when the coordinates of the sprite become equal to those of its
0271     * destination point
0272     */
0273   void atDestination(AnimSprite* sprite);
0274 
0275   void animationFinished(AnimSprite* sprite);
0276 
0277 protected:
0278   bool sceneEvent ( QEvent *  ) override {return false;}
0279 
0280   /**
0281     * Set this sprite to display its numFrame's frame. If numFrame is greater
0282     * than the number of frames of the sprite, do nothing
0283     * @param numFrame The number of the frame to display
0284     */
0285   void setFrame(unsigned int numFrame);
0286 
0287   /**
0288     * Builds the sequence of images of this sprite using the SVG renderer and
0289     * data about zoom factor, look direction, etc. 
0290     */
0291   void sequenceConstruction();
0292 
0293   /**
0294     * changes the direction of this sprite's look
0295     */
0296   void setLook(TDir);
0297 
0298   bool m_animated;
0299 
0300   /**
0301    * Zoom factor
0302    */
0303   double m_zoom;
0304   
0305   private:
0306   QString m_svgid;
0307 
0308   /**
0309     * Change the active frame to the next one in the list. Use the first one
0310     * if the current frame was the last one
0311     *
0312     */
0313   void nextFrame();
0314 
0315   /**
0316   * Direction of the look of the sprite (left or right) ;
0317   * Allows to select the good image sequence
0318   */
0319   TDir look;
0320 
0321   /**
0322     * The number of versions of the sprite
0323     */
0324   unsigned int nbVersions;
0325 
0326   /**
0327     * The background onto which the sprite will be displayed
0328     */
0329   BackGnd *backGnd;
0330 
0331   /**
0332     * For a sprite moving from one country to another, the destination one ;
0333     * NULL otherwise.
0334     */
0335   GameLogic::Country *destination;
0336 
0337   /**
0338     * The coordinates of the destination (gun point or flag point for example)
0339     */
0340   QPointF destinationPoint;
0341 
0342   /**
0343     * the number of images in a version of the sprite
0344     */
0345   unsigned int frames;
0346 
0347   /**
0348     * the number of the current image in the current version of the sprite
0349     */
0350   unsigned int actFrame;
0351 
0352   /**
0353     * The attacking state of the sprite
0354     */
0355   State myState;
0356 
0357   /**
0358     * Position information needed to load graphics from the pool
0359     */
0360   double m_height, m_width;
0361 
0362   /** If this member is true, the sprite should approach its destination by
0363     * the left. So, if it is at the right side of its dest, it will continue
0364     * towards right up to the right side of the world. There, it will jump at
0365     * the left side and continue directly towards its destination.
0366     * When this member is set to true, the sprite should set
0367     * approachDestByRight to false. If both are false, the sprite will go
0368     * directly towards its destination.
0369     */
0370   bool approachDestByLeft ;
0371 
0372   /** If this member is true, the sprite should approach its destination by
0373     * the right. So, if it is at the left side of its dest, it will continue
0374     * towards left up to the left side of the world. There, it will jump at
0375     * the right side and continue directly towards its destination.
0376     * When this member is set to true, the sprite should set
0377     * approachDestByLeft to false. If both are false, the sprite will go
0378     * directly towards its destination.
0379     */
0380   bool approachDestByRight;
0381 
0382   /** If this member is true, the sprite should approach its destination by
0383     * the top. So, if it is under its dest, it will continue
0384     * towards the bottom down to the bottom side of the world. There, it will
0385     *  jump at the top side and continue directly towards its destination.
0386     * When this member is set to true, the sprite should set
0387     * approachDestByBottom to false. If both are false, the sprite will go
0388     * directly towards its destination.
0389     */
0390   bool approachDestByTop ;
0391 
0392   /** If this member is true, the sprite should approach its destination by
0393     * the bottom. So, if it is upper its dest, it will continue
0394     * towards the top up to the top side of the world. There, it will jump at
0395     * the bottom side and continue directly towards its destination.
0396     * When this member is set to true, the sprite should set
0397     * approachDestByTop to false. If both are false, the sprite will go
0398     * directly towards its destination.
0399     */
0400   bool approachDestByBottom;
0401 
0402 
0403   /**
0404     * Stores the images of this sprite for all its directions with the current
0405     * SVG file and zoom factor.
0406     */
0407   QList<QPixmap> m_frames;
0408 
0409   /**
0410     * This SVG renderer stores the SVG file of this sprite, renders it at the
0411     * desired zoom factor and the result is used to fill the frames list
0412     */
0413   QSvgRenderer* m_renderer;
0414 
0415   unsigned int m_numberOfShots;
0416 
0417   QTimer m_timer;
0418 
0419   QString m_skin;
0420 };
0421 
0422 } // closing namespace Ksirk
0423 
0424 #endif // ANIMSPRITE_H