File indexing completed on 2024-04-21 04:02:00

0001 /*
0002     This file is part of the KDE project "KAtomic"
0003 
0004     SPDX-FileCopyrightText: 2006-2007 Dmitry Suzdalev <dimsuz@gmail.com>
0005     SPDX-FileCopyrightText: 2010 Brian Croom <brian.s.croom@gmail.com>
0006 
0007     SPDX-License-Identifier: GPL-2.0-or-later
0008 */
0009 
0010 #ifndef PLAYFIELD_H
0011 #define PLAYFIELD_H
0012 
0013 #include "commondefs.h"
0014 
0015 #include <KGameRenderer>
0016 
0017 #include <QGraphicsScene>
0018 #include <QList>
0019 #include <QStack>
0020 
0021 #define MIN_ELEM_SIZE 30
0022 
0023 class KConfigGroup;
0024 class AtomFieldItem;
0025 class ArrowFieldItem;
0026 class MoleculePreviewItem;
0027 class QTimeLine;
0028 class KGamePopupItem;
0029 class LevelData;
0030 
0031 /**
0032  *  KAtomic level playfield
0033  */
0034 class PlayField : public QGraphicsScene
0035 {
0036     Q_OBJECT
0037 public:
0038     enum Direction { Up=0, Down, Left, Right };
0039     explicit PlayField( QObject *parent );
0040     ~PlayField() override;
0041     /**
0042      *  Resizes playfield to width,height
0043      */
0044     void resize( int width, int height );
0045     /**
0046      *  Loads level
0047      */
0048     void setLevelData(const LevelData* level);
0049     /**
0050      *  Sets animation speed (0-slow, 1-normal, 2-fast)
0051      */
0052     void setAnimationSpeed(int speed);
0053     /**
0054      *  Animates currently selected atom movement in direction dir
0055      *  @param numCells used on undos/redos
0056      */
0057     void moveSelectedAtom( Direction dir, int numCells=0 );
0058     /**
0059      *  Saves the current game to config object
0060      */
0061     void saveGame(KConfigGroup& config) const;
0062     /**
0063      *  Loads game from config object
0064      */
0065     void loadGame(const KConfigGroup& config);
0066     /**
0067      *  Returns whether level is finished already
0068      */
0069     bool isLevelFinished() const { return m_levelFinished; }
0070     /**
0071      * Displays a passive popup message at the bottom of the scene
0072      */
0073     void showMessage( const QString& message );
0074     /**
0075      * Name of the current molecule
0076      */
0077     QString moleculeName() const;
0078     /**
0079      * The caching SVG pixmap renderer
0080      */
0081     KGameRenderer* renderer() { return &m_renderer; }
0082 
0083 public Q_SLOTS:
0084     /**
0085      *  Selects next atom
0086      */
0087     void nextAtom();
0088     /**
0089      *  Selects previous atom
0090      */
0091     void previousAtom();
0092     /**
0093      *  Undoes one movement
0094      */
0095     void undo();
0096     /**
0097      *  Redoes one movement
0098      */
0099     void redo();
0100     /**
0101      *  Undoes all movements
0102      */
0103     void undoAll();
0104     /**
0105      *  Redoes all movements
0106      */
0107     void redoAll();
0108 Q_SIGNALS:
0109     void gameOver(int numMoves);
0110     void updateMoves(int);
0111     void enableUndo(bool);
0112     void enableRedo(bool);
0113 private Q_SLOTS:
0114     void atomAnimFrameChanged(int frame);
0115 private:
0116     void drawForeground( QPainter*, const QRectF& ) override;
0117     void mousePressEvent( QGraphicsSceneMouseEvent* ev ) override;
0118 
0119     /**
0120      *  Checks if molecule is finished
0121      */
0122     bool checkDone() const;
0123     /**
0124      *  Re-renders atoms&arrows Pixmaps, updates their positions
0125      */
0126     void updateFieldItems();
0127     /**
0128      *  Updates arrows around selected atom
0129      */
0130     void updateArrows(bool justHide=false);
0131     /**
0132      * Set the background brush to a properly sized pixmap
0133      */
0134     void updateBackground();
0135     /**
0136      *  Returns true if Field cell (x,y) is empty, i.e. it isn't a wall and has no atom
0137      */
0138     bool cellIsEmpty(int x, int y) const;
0139     /**
0140      *  Returns true if atom animation is running
0141      */
0142     bool isAnimating() const;
0143 
0144     inline int toPixX( int fieldX ) const { return fieldX*m_elemSize; }
0145     inline int toPixY( int fieldY ) const { return fieldY*m_elemSize; }
0146     inline int toFieldX( int pixX ) const { return pixX/m_elemSize; }
0147     inline int toFieldY( int pixY ) const { return pixY/m_elemSize; }
0148     inline int fieldCenterX() const { return toPixX(0) + m_elemSize*FIELD_SIZE/2; }
0149     inline int fieldCenterY() const { return toPixY(0) + m_elemSize*FIELD_SIZE/2; }
0150 
0151     /**
0152      * Renderer object
0153      */
0154     KGameRenderer m_renderer;
0155     /**
0156      *  Number of moves made for current level
0157      */
0158     int m_numMoves;
0159     /**
0160      * Level Data
0161      */
0162     const LevelData* m_levelData;
0163     /**
0164      *  Element (i.e. atom, wall, arrow) size
0165      */
0166     int m_elemSize;
0167     /**
0168      *  List of atom QGraphicsItems
0169      */
0170     QList<AtomFieldItem*> m_atoms;
0171     /**
0172      *  Arrow items
0173      */
0174     ArrowFieldItem *m_upArrow, *m_leftArrow, *m_downArrow, *m_rightArrow;
0175     /**
0176      * Item used to show messages to user
0177      */
0178     KGamePopupItem *m_messageItem;
0179     /**
0180      *  Index of currently selected atom
0181      */
0182     int m_selIdx;
0183     /**
0184      *  Direction in which current atom animation moves
0185      */
0186     Direction m_dir;
0187     /**
0188      *  Animation speed. Atom will move at 1cell in m_animSpeed msec speed
0189      */
0190     int m_animSpeed;
0191     /**
0192      *  Timeline object to control atom movement animation
0193      */
0194     QTimeLine *m_atomTimeLine;
0195     /**
0196      *  True if current level is finished and thus all player input should be disabled
0197      */
0198     bool m_levelFinished;
0199 
0200     struct AtomMove
0201     {
0202         int atomIdx; // atom index in m_atoms
0203         Direction dir;
0204         int numCells;
0205         AtomMove( int idx=-1, Direction d=Up, int nc=0 )
0206             : atomIdx(idx), dir(d), numCells(nc) { }
0207     };
0208     QStack<AtomMove> m_undoStack;
0209     QStack<AtomMove> m_redoStack;
0210 
0211     MoleculePreviewItem *m_previewItem;
0212 };
0213 
0214 #endif