1/*******************************************************************
2 *
3 * Copyright 2006 Dmitry Suzdalev <dimsuz@gmail.com>
4 *
5 * This file is part of the KDE project "KLines"
6 *
7 * KLines is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2, or (at your option)
10 * any later version.
11 *
12 * KLines is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * 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 * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
21 *
22 ********************************************************************/
23#ifndef KL_SCENE_H
24#define KL_SCENE_H
25
26#include <QGraphicsScene>
27#include <KRandomSequence>
28
29#include "commondefs.h"
30
31static const int FIELD_SIZE=9;
32
33class KLinesAnimator;
34class BallItem;
35class PreviewItem;
36class QGraphicsRectItem;
37class KGamePopupItem;
38
39/**
40 * Displays and drives the game
41 */
42class KLinesScene : public QGraphicsScene
43{
44 Q_OBJECT
45public:
46 explicit KLinesScene( QObject *parent );
47 ~KLinesScene();
48 /**
49 * Resizes scene
50 */
51 void resizeScene( int width, int height );
52 /**
53 * Brings in next three balls to scene
54 */
55 void nextThreeBalls();
56 /**
57 * Show/Hide the preview zone
58 */
59 void setPreviewZoneVisible( bool visible );
60 /**
61 * This score points will be added as an additional bonus to
62 * every score resulted from ball erasing event.
63 * For example 1 score point is added if the game is played with
64 * hidden preview widget.
65 * By default no bonus is added.
66 */
67 void setBonusScorePoints( int points ) { m_bonusScore = points; }
68 /**
69 * Returns colors of the 3 balls in the next turn
70 */
71 QList<BallColor> nextColors() const { return m_nextColors; }
72 /**
73 * Returns ballitem in field position pos or 0 if there
74 * is no item there
75 */
76 BallItem* ballAt( const FieldPos& pos ) { return m_field[pos.x][pos.y]; }
77 /**
78 * Overloaded above function
79 */
80 BallItem* ballAt( int x, int y ) { return m_field[x][y]; }
81 /**
82 * Field coords to pixel coords
83 */
84 inline QPointF fieldToPix(const FieldPos& fpos) const
85 {
86 return QPointF( m_playFieldRect.x() + m_playFieldBorderSize + fpos.x*m_cellSize,
87 m_playFieldRect.y() + m_playFieldBorderSize + fpos.y*m_cellSize );
88 }
89 /**
90 * Pixel coords to field coords
91 */
92 inline FieldPos pixToField( const QPointF& p ) const
93 {
94 return FieldPos(static_cast<int>(( p.x()-m_playFieldRect.x()-m_playFieldBorderSize )/m_cellSize),
95 static_cast<int>(( p.y()-m_playFieldRect.y()-m_playFieldBorderSize )/m_cellSize));
96 }
97public slots:
98 /**
99 * Starts new game
100 */
101 void startNewGame();
102 /**
103 * Ends current and starts next turn explicitly
104 */
105 void endTurn();
106 /**
107 * Undoes one move
108 */
109 void undo();
110 /**
111 * Moves keyboard-playing focus rect to the left
112 */
113 void moveFocusLeft();
114 /**
115 * Moves keyboard-playing focus rect to the right
116 */
117 void moveFocusRight();
118 /**
119 * Moves keyboard-playing focus rect to the up
120 */
121 void moveFocusUp();
122 /**
123 * Moves keyboard-playing focus rect to the down
124 */
125 void moveFocusDown();
126 /**
127 * Takes corresponding action on cell under focus rect
128 */
129 void cellSelected();
130signals:
131 void scoreChanged(int);
132 void stateChanged(const QString &);
133 void gameOver(int);
134private slots:
135 void moveAnimFinished();
136 void removeAnimFinished();
137 void bornAnimFinished();
138private:
139 /**
140 * Creates a ball and places it in random free cell
141 * @param c color of the ball
142 * @return ball placed
143 */
144 BallItem* randomlyPlaceBall(BallColor c);
145 /**
146 * Searches for 5 or more balls in a row and deletes them from field
147 */
148 void searchAndErase();
149 /**
150 * This function takes one of two actions:
151 * If there's a ball at fpos, it will be selected.
152 * Otherwise if the cell at fpos is empty and there's
153 * a selected ball in some other cell it will be moved to fpos
154 * (if the move is possible, of course)
155 */
156 void selectOrMove( const FieldPos& fpos );
157 /**
158 * Saves game state information to be used during undo
159 */
160 void saveUndoInfo();
161 /** Does some actions upon game over. Called from various places where
162 * it is clear that game is now over. emits gameOver(int) signal
163 */
164 void gameOverHandler();
165
166 virtual void drawBackground( QPainter*, const QRectF& );
167 virtual void mousePressEvent( QGraphicsSceneMouseEvent* );
168
169 /**
170 * This array represents the play field.
171 * Each cell holds the pointer to BallItem
172 * or 0 if there's no ball in that cell
173 */
174 BallItem* m_field[FIELD_SIZE][FIELD_SIZE];
175 /**
176 * Used to start game animations
177 * This object knows how to do some ball animations
178 */
179 KLinesAnimator* m_animator;
180 /**
181 * We need random numbers in this game
182 */
183 KRandomSequence m_randomSeq;
184 /**
185 * Area of playfield (with border included - if any exists in theme)
186 */
187 QRect m_playFieldRect;
188 /**
189 * Size of a playfield border.
190 * Equals 0 if there's no border element in current theme
191 */
192 int m_playFieldBorderSize;
193
194 /**
195 * Position of selected ball (-1,-1) if none
196 */
197 FieldPos m_selPos;
198 /**
199 * Number of free cells in the field
200 */
201 int m_numFreeCells;
202 /**
203 * Current game score
204 */
205 int m_score;
206 /**
207 * Bonus points added to score upon ball erasing
208 * @see setBonusScorePoints()
209 */
210 int m_bonusScore;
211 /**
212 * Cell size in pixels
213 */
214 int m_cellSize;
215 /**
216 * Is true if preview zone is visible
217 */
218 bool m_previewZoneVisible;
219 /**
220 * Varable which is needed for little trick (tm).
221 * Read more about it in removeAnimFinished() slot
222 */
223 bool m_placeBalls;
224 /**
225 * Items pending for removal after remove-anim finishes
226 */
227 QList<BallItem*> m_itemsToDelete;
228 /**
229 * Colors of the next turn's balls
230 */
231 QList<BallColor> m_nextColors;
232 /**
233 * Keyboard-playing focus indication
234 */
235 QGraphicsRectItem *m_focusItem;
236 /**
237 * Item which displays next balls preview
238 */
239 PreviewItem *m_previewItem;
240 /**
241 * Item to show popup messages to user
242 */
243 KGamePopupItem *m_popupItem;
244 /**
245 * Struct for holding game state - used on undos
246 */
247 struct UndoInfo
248 {
249 int numFreeCells;
250 int score;
251 QList<BallColor> nextColors;
252 BallColor fcolors[FIELD_SIZE][FIELD_SIZE];
253 };
254 /**
255 * Holds game state for undo.
256 * It is saved before every new turn
257 */
258 UndoInfo m_undoInfo;
259 bool m_gameOver;
260};
261
262#endif
263