scene.h 7.17 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
/*******************************************************************
 *
 * Copyright 2006 Dmitry Suzdalev <dimsuz@gmail.com>
 *
 * This file is part of the KDE project "KLines"
 *
 * KLines is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * KLines is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
18
 * along with KLines; see the file COPYING.  If not, write to
19 20 21 22 23 24 25 26
 * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 *
 ********************************************************************/
#ifndef KL_SCENE_H
#define KL_SCENE_H

#include <QGraphicsScene>
Anuj Pahuja's avatar
Anuj Pahuja committed
27

Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
28 29
#include <KRandomSequence>

30 31 32 33
#include "commondefs.h"

static const int FIELD_SIZE=9;

Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
34
class KLinesAnimator;
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
35
class BallItem;
36
class PreviewItem;
37
class QGraphicsRectItem;
38
class KGamePopupItem;
39

40 41 42
/**
 *  Displays and drives the game
 */
43 44
class KLinesScene : public QGraphicsScene
{
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
45
    Q_OBJECT
46
public:
47
    explicit KLinesScene( QObject *parent );
48
    ~KLinesScene();
49 50 51
    /**
     *  Resizes scene
     */
52
    void resizeScene( int width, int height );
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
53 54 55 56
    /**
     *  Brings in next three balls to scene
     */
    void nextThreeBalls();
57 58 59 60
    /**
     *  Show/Hide the preview zone
     */
    void setPreviewZoneVisible( bool visible );
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
61 62 63 64 65 66 67 68
    /**
     *  This score points will be added as an additional bonus to
     *  every score resulted from ball erasing event.
     *  For example 1 score point is added if the game is played with
     *  hidden preview widget.
     *  By default no bonus is added.
     */
    void setBonusScorePoints( int points ) { m_bonusScore = points; }
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
69 70 71 72
    /**
     *  Returns colors of the 3 balls in the next turn
     */
    QList<BallColor> nextColors() const { return m_nextColors; }
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
73
    /**
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
74 75
     *  Returns ballitem in field position pos or 0 if there
     *  is no item there
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
76
     */
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
77
    BallItem* ballAt( const FieldPos& pos ) { return m_field[pos.x][pos.y]; }
78 79 80 81
    /**
     * Overloaded above function
     */
    BallItem* ballAt( int x, int y ) { return m_field[x][y]; }
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
82 83 84
    /**
     *  Field coords to pixel coords
     */
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
85 86
    inline QPointF fieldToPix(const FieldPos& fpos) const
    {
87 88
        return QPointF( m_playFieldRect.x() + m_playFieldBorderSize + fpos.x*m_cellSize,
                        m_playFieldRect.y() + m_playFieldBorderSize + fpos.y*m_cellSize );
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
89
    }
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
90 91 92
    /**
     *  Pixel coords to field coords
     */
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
93 94
    inline FieldPos pixToField( const QPointF& p ) const
    {
95 96
        return FieldPos(static_cast<int>(( p.x()-m_playFieldRect.x()-m_playFieldBorderSize )/m_cellSize),
                        static_cast<int>(( p.y()-m_playFieldRect.y()-m_playFieldBorderSize )/m_cellSize));
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
97
    }
Laurent Montel's avatar
Laurent Montel committed
98
public Q_SLOTS:
99 100 101 102
    /**
     *  Starts new game
     */
    void startNewGame();
Laurent Montel's avatar
Laurent Montel committed
103 104 105 106
    /**
     * Ends game
     */
    void endGame();
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
107 108 109 110 111 112 113 114
    /**
     *  Ends current and starts next turn explicitly
     */
    void endTurn();
    /**
     *  Undoes one move
     */
    void undo();
115
    /**
116
     *  Moves keyboard-playing focus rect to the left
117 118 119
     */
    void moveFocusLeft();
    /**
120
     *  Moves keyboard-playing focus rect to the right
121 122 123
     */
    void moveFocusRight();
    /**
124
     *  Moves keyboard-playing focus rect to the up
125 126 127
     */
    void moveFocusUp();
    /**
128
     *  Moves keyboard-playing focus rect to the down
129 130 131 132 133 134
     */
    void moveFocusDown();
    /**
     *  Takes corresponding action on cell under focus rect
     */
    void cellSelected();
Laurent Montel's avatar
Laurent Montel committed
135
Q_SIGNALS:
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
136
    void scoreChanged(int);
Simon Huerlimann's avatar
Simon Huerlimann committed
137
    void stateChanged(const QString &);
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
138
    void gameOver(int);
Laurent Montel's avatar
Laurent Montel committed
139
private Q_SLOTS:
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
140
    void moveAnimFinished();
141 142
    void removeAnimFinished();
    void bornAnimFinished();
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
143 144
private:
    /**
145 146
     *  Creates a ball and places it in random free cell
     *  @param c color of the ball
147
     *  @return ball placed
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
148
     */
149
    BallItem* randomlyPlaceBall(BallColor c);
150 151 152
    /**
     *  Searches for 5 or more balls in a row and deletes them from field
     */
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
153
    void searchAndErase();
154
    /**
Mauricio Piacentini's avatar
Mauricio Piacentini committed
155
     *  This function takes one of two actions:
156
     *  If there's a ball at fpos, it will be selected.
157
     *  Otherwise if the cell at fpos is empty and there's
158 159 160 161
     *  a selected ball in some other cell it will be moved to fpos
     *  (if the move is possible, of course)
     */
    void selectOrMove( const FieldPos& fpos );
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
162 163 164 165
    /**
     *  Saves game state information to be used during undo
     */
    void saveUndoInfo();
166 167 168 169
    /** Does some actions upon game over. Called from various places where
     * it is clear that game is now over. emits gameOver(int) signal
     */
    void gameOverHandler();
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
170

Laurent Montel's avatar
Laurent Montel committed
171 172
    void drawBackground( QPainter*, const QRectF& ) Q_DECL_OVERRIDE;
    void mousePressEvent( QGraphicsSceneMouseEvent* ) Q_DECL_OVERRIDE;
173

Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
174 175 176 177 178 179
    /**
     *  This array represents the play field.
     *  Each cell holds the pointer to BallItem
     *  or 0 if there's no ball in that cell
     */
    BallItem* m_field[FIELD_SIZE][FIELD_SIZE];
180 181 182 183
    /**
     *  Used to start game animations
     *  This object knows how to do some ball animations
     */
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
184
    KLinesAnimator* m_animator;
185 186 187
    /**
     * We need random numbers in this game
     */
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
188
    KRandomSequence m_randomSeq;
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
189
    /**
190
     * Area of playfield (with border included - if any exists in theme)
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
191
     */
192 193 194 195 196 197 198
    QRect m_playFieldRect;
    /**
     * Size of a playfield border.
     * Equals 0 if there's no border element in current theme
     */
    int m_playFieldBorderSize;

Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
199
    /**
200
     *  Position of selected ball (-1,-1) if none
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
201
     */
202
    FieldPos m_selPos;
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
203
    /**
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
204 205 206 207 208
     *  Number of free cells in the field
     */
    int m_numFreeCells;
    /**
     *  Current game score
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
209
     */
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
210
    int m_score;
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
211 212 213 214 215
    /**
     *  Bonus points added to score upon ball erasing
     *  @see setBonusScorePoints()
     */
    int m_bonusScore;
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
216 217 218 219
    /**
     *  Cell size in pixels
     */
    int m_cellSize;
220 221 222 223
    /**
     *  Is true if preview zone is visible
     */
    bool m_previewZoneVisible;
224 225 226 227
    /**
     *  Varable which is needed for little trick (tm).
     *  Read more about it in removeAnimFinished() slot
     */
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
228
    bool m_placeBalls;
229 230 231 232
    /**
     *  Items pending for removal after remove-anim finishes
     */
    QList<BallItem*> m_itemsToDelete;
233 234 235 236
    /**
     *  Colors of the next turn's balls
     */
    QList<BallColor> m_nextColors;
237 238 239 240
    /**
     *  Keyboard-playing focus indication
     */
    QGraphicsRectItem *m_focusItem;
241 242 243 244
    /**
     *  Item which displays next balls preview
     */
    PreviewItem *m_previewItem;
245 246 247 248
    /**
     * Item to show popup messages to user
     */
    KGamePopupItem *m_popupItem;
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
249 250 251 252 253 254 255 256 257 258 259 260 261 262 263
    /**
     *  Struct for holding game state - used on undos
     */
    struct UndoInfo
    {
        int numFreeCells;
        int score;
        QList<BallColor> nextColors;
        BallColor fcolors[FIELD_SIZE][FIELD_SIZE];
    };
    /**
     *  Holds game state for undo.
     *  It is saved before every new turn
     */
    UndoInfo m_undoInfo;
264
    bool m_gameOver;
265 266 267
};

#endif