scene.h 6.61 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
27
 * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 *
 ********************************************************************/
#ifndef KL_SCENE_H
#define KL_SCENE_H

#include <QGraphicsScene>
#include <QGraphicsView>
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 QGraphicsRectItem;
37

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

161
    virtual void drawBackground( QPainter*, const QRectF& );
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
162
    virtual void mousePressEvent( QGraphicsSceneMouseEvent* );
163

Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
164
165
166
167
168
169
    /**
     *  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];
170
171
172
173
    /**
     *  Used to start game animations
     *  This object knows how to do some ball animations
     */
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
174
    KLinesAnimator* m_animator;
175
176
177
    /**
     * We need random numbers in this game
     */
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
178
    KRandomSequence m_randomSeq;
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
179
180
181
182
    /**
     * Origin of playfield
     */
    QPoint m_playFieldOrigin;
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
183
    /**
184
     *  Position of selected ball (-1,-1) if none
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
185
     */
186
    FieldPos m_selPos;
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
187
    /**
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
188
189
190
191
192
     *  Number of free cells in the field
     */
    int m_numFreeCells;
    /**
     *  Current game score
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
193
     */
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
194
    int m_score;
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
195
196
197
198
199
    /**
     *  Bonus points added to score upon ball erasing
     *  @see setBonusScorePoints()
     */
    int m_bonusScore;
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
200
201
202
203
    /**
     *  Cell size in pixels
     */
    int m_cellSize;
204
205
206
207
    /**
     *  Is true if preview zone is visible
     */
    bool m_previewZoneVisible;
208
209
210
211
    /**
     *  Varable which is needed for little trick (tm).
     *  Read more about it in removeAnimFinished() slot
     */
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
212
    bool m_placeBalls;
213
214
215
216
    /**
     *  Items pending for removal after remove-anim finishes
     */
    QList<BallItem*> m_itemsToDelete;
217
218
219
220
    /**
     *  Colors of the next turn's balls
     */
    QList<BallColor> m_nextColors;
221
222
223
224
    /**
     *  Keyboard-playing focus indication
     */
    QGraphicsRectItem *m_focusItem;
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
    /**
     *  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;
240
241
242
243
244
245
246
247
248
249
250
};

class KLinesView : public QGraphicsView
{
public:
    KLinesView( KLinesScene* scene, QWidget *parent );
private:
    void resizeEvent(QResizeEvent *);
};

#endif