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

153
    virtual void drawBackground( QPainter*, const QRectF& );
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
154
    virtual void mousePressEvent( QGraphicsSceneMouseEvent* );
155

Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
156
157
158
159
160
161
    /**
     *  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];
162
163
164
165
    /**
     *  Used to start game animations
     *  This object knows how to do some ball animations
     */
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
166
    KLinesAnimator* m_animator;
167
168
169
    /**
     * We need random numbers in this game
     */
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
170
    KRandomSequence m_randomSeq;
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
171
    /**
172
     *  Position of selected ball (-1,-1) if none
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
173
     */
174
    FieldPos m_selPos;
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
175
    /**
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
176
177
178
179
180
     *  Number of free cells in the field
     */
    int m_numFreeCells;
    /**
     *  Current game score
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
181
     */
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
182
    int m_score;
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
183
184
185
186
187
    /**
     *  Bonus points added to score upon ball erasing
     *  @see setBonusScorePoints()
     */
    int m_bonusScore;
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
188
189
190
191
    /**
     *  Cell size in pixels
     */
    int m_cellSize;
192
193
194
195
    /**
     *  Varable which is needed for little trick (tm).
     *  Read more about it in removeAnimFinished() slot
     */
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
196
    bool m_placeBalls;
197
198
199
200
    /**
     *  Items pending for removal after remove-anim finishes
     */
    QList<BallItem*> m_itemsToDelete;
201
202
203
204
    /**
     *  Colors of the next turn's balls
     */
    QList<BallColor> m_nextColors;
205
206
207
208
    /**
     *  Keyboard-playing focus indication
     */
    QGraphicsRectItem *m_focusItem;
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224

    /**
     *  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;
225
226
227
228
229
230
231
232
233
234
235
};

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

#endif