source: trunk/examples/widgets/tetrix/tetrixboard.cpp@ 651

Last change on this file since 651 was 651, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.2 sources.

File size: 9.7 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the examples of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include <QtGui>
43
44#include "tetrixboard.h"
45
46//! [0]
47TetrixBoard::TetrixBoard(QWidget *parent)
48 : QFrame(parent)
49{
50 setFrameStyle(QFrame::Panel | QFrame::Sunken);
51 setFocusPolicy(Qt::StrongFocus);
52 isStarted = false;
53 isPaused = false;
54 clearBoard();
55
56 nextPiece.setRandomShape();
57}
58//! [0]
59
60//! [1]
61void TetrixBoard::setNextPieceLabel(QLabel *label)
62{
63 nextPieceLabel = label;
64}
65//! [1]
66
67//! [2]
68QSize TetrixBoard::sizeHint() const
69{
70 return QSize(BoardWidth * 15 + frameWidth() * 2,
71 BoardHeight * 15 + frameWidth() * 2);
72}
73
74QSize TetrixBoard::minimumSizeHint() const
75//! [2] //! [3]
76{
77 return QSize(BoardWidth * 5 + frameWidth() * 2,
78 BoardHeight * 5 + frameWidth() * 2);
79}
80//! [3]
81
82//! [4]
83void TetrixBoard::start()
84{
85 if (isPaused)
86 return;
87
88 isStarted = true;
89 isWaitingAfterLine = false;
90 numLinesRemoved = 0;
91 numPiecesDropped = 0;
92 score = 0;
93 level = 1;
94 clearBoard();
95
96 emit linesRemovedChanged(numLinesRemoved);
97 emit scoreChanged(score);
98 emit levelChanged(level);
99
100 newPiece();
101 timer.start(timeoutTime(), this);
102}
103//! [4]
104
105//! [5]
106void TetrixBoard::pause()
107{
108 if (!isStarted)
109 return;
110
111 isPaused = !isPaused;
112 if (isPaused) {
113 timer.stop();
114 } else {
115 timer.start(timeoutTime(), this);
116 }
117 update();
118//! [5] //! [6]
119}
120//! [6]
121
122//! [7]
123void TetrixBoard::paintEvent(QPaintEvent *event)
124{
125 QFrame::paintEvent(event);
126
127 QPainter painter(this);
128 QRect rect = contentsRect();
129//! [7]
130
131 if (isPaused) {
132 painter.drawText(rect, Qt::AlignCenter, tr("Pause"));
133 return;
134 }
135
136//! [8]
137 int boardTop = rect.bottom() - BoardHeight*squareHeight();
138
139 for (int i = 0; i < BoardHeight; ++i) {
140 for (int j = 0; j < BoardWidth; ++j) {
141 TetrixShape shape = shapeAt(j, BoardHeight - i - 1);
142 if (shape != NoShape)
143 drawSquare(painter, rect.left() + j * squareWidth(),
144 boardTop + i * squareHeight(), shape);
145 }
146//! [8] //! [9]
147 }
148//! [9]
149
150//! [10]
151 if (curPiece.shape() != NoShape) {
152 for (int i = 0; i < 4; ++i) {
153 int x = curX + curPiece.x(i);
154 int y = curY - curPiece.y(i);
155 drawSquare(painter, rect.left() + x * squareWidth(),
156 boardTop + (BoardHeight - y - 1) * squareHeight(),
157 curPiece.shape());
158 }
159//! [10] //! [11]
160 }
161//! [11] //! [12]
162}
163//! [12]
164
165//! [13]
166void TetrixBoard::keyPressEvent(QKeyEvent *event)
167{
168 if (!isStarted || isPaused || curPiece.shape() == NoShape) {
169 QFrame::keyPressEvent(event);
170 return;
171 }
172//! [13]
173
174//! [14]
175 switch (event->key()) {
176 case Qt::Key_Left:
177 tryMove(curPiece, curX - 1, curY);
178 break;
179 case Qt::Key_Right:
180 tryMove(curPiece, curX + 1, curY);
181 break;
182 case Qt::Key_Down:
183 tryMove(curPiece.rotatedRight(), curX, curY);
184 break;
185 case Qt::Key_Up:
186 tryMove(curPiece.rotatedLeft(), curX, curY);
187 break;
188 case Qt::Key_Space:
189 dropDown();
190 break;
191 case Qt::Key_D:
192 oneLineDown();
193 break;
194 default:
195 QFrame::keyPressEvent(event);
196 }
197//! [14]
198}
199
200//! [15]
201void TetrixBoard::timerEvent(QTimerEvent *event)
202{
203 if (event->timerId() == timer.timerId()) {
204 if (isWaitingAfterLine) {
205 isWaitingAfterLine = false;
206 newPiece();
207 timer.start(timeoutTime(), this);
208 } else {
209 oneLineDown();
210 }
211 } else {
212 QFrame::timerEvent(event);
213//! [15] //! [16]
214 }
215//! [16] //! [17]
216}
217//! [17]
218
219//! [18]
220void TetrixBoard::clearBoard()
221{
222 for (int i = 0; i < BoardHeight * BoardWidth; ++i)
223 board[i] = NoShape;
224}
225//! [18]
226
227//! [19]
228void TetrixBoard::dropDown()
229{
230 int dropHeight = 0;
231 int newY = curY;
232 while (newY > 0) {
233 if (!tryMove(curPiece, curX, newY - 1))
234 break;
235 --newY;
236 ++dropHeight;
237 }
238 pieceDropped(dropHeight);
239//! [19] //! [20]
240}
241//! [20]
242
243//! [21]
244void TetrixBoard::oneLineDown()
245{
246 if (!tryMove(curPiece, curX, curY - 1))
247 pieceDropped(0);
248}
249//! [21]
250
251//! [22]
252void TetrixBoard::pieceDropped(int dropHeight)
253{
254 for (int i = 0; i < 4; ++i) {
255 int x = curX + curPiece.x(i);
256 int y = curY - curPiece.y(i);
257 shapeAt(x, y) = curPiece.shape();
258 }
259
260 ++numPiecesDropped;
261 if (numPiecesDropped % 25 == 0) {
262 ++level;
263 timer.start(timeoutTime(), this);
264 emit levelChanged(level);
265 }
266
267 score += dropHeight + 7;
268 emit scoreChanged(score);
269 removeFullLines();
270
271 if (!isWaitingAfterLine)
272 newPiece();
273//! [22] //! [23]
274}
275//! [23]
276
277//! [24]
278void TetrixBoard::removeFullLines()
279{
280 int numFullLines = 0;
281
282 for (int i = BoardHeight - 1; i >= 0; --i) {
283 bool lineIsFull = true;
284
285 for (int j = 0; j < BoardWidth; ++j) {
286 if (shapeAt(j, i) == NoShape) {
287 lineIsFull = false;
288 break;
289 }
290 }
291
292 if (lineIsFull) {
293//! [24] //! [25]
294 ++numFullLines;
295 for (int k = i; k < BoardHeight - 1; ++k) {
296 for (int j = 0; j < BoardWidth; ++j)
297 shapeAt(j, k) = shapeAt(j, k + 1);
298 }
299//! [25] //! [26]
300 for (int j = 0; j < BoardWidth; ++j)
301 shapeAt(j, BoardHeight - 1) = NoShape;
302 }
303//! [26] //! [27]
304 }
305//! [27]
306
307//! [28]
308 if (numFullLines > 0) {
309 numLinesRemoved += numFullLines;
310 score += 10 * numFullLines;
311 emit linesRemovedChanged(numLinesRemoved);
312 emit scoreChanged(score);
313
314 timer.start(500, this);
315 isWaitingAfterLine = true;
316 curPiece.setShape(NoShape);
317 update();
318 }
319//! [28] //! [29]
320}
321//! [29]
322
323//! [30]
324void TetrixBoard::newPiece()
325{
326 curPiece = nextPiece;
327 nextPiece.setRandomShape();
328 showNextPiece();
329 curX = BoardWidth / 2 + 1;
330 curY = BoardHeight - 1 + curPiece.minY();
331
332 if (!tryMove(curPiece, curX, curY)) {
333 curPiece.setShape(NoShape);
334 timer.stop();
335 isStarted = false;
336 }
337//! [30] //! [31]
338}
339//! [31]
340
341//! [32]
342void TetrixBoard::showNextPiece()
343{
344 if (!nextPieceLabel)
345 return;
346
347 int dx = nextPiece.maxX() - nextPiece.minX() + 1;
348 int dy = nextPiece.maxY() - nextPiece.minY() + 1;
349
350 QPixmap pixmap(dx * squareWidth(), dy * squareHeight());
351 QPainter painter(&pixmap);
352 painter.fillRect(pixmap.rect(), nextPieceLabel->palette().background());
353
354 for (int i = 0; i < 4; ++i) {
355 int x = nextPiece.x(i) - nextPiece.minX();
356 int y = nextPiece.y(i) - nextPiece.minY();
357 drawSquare(painter, x * squareWidth(), y * squareHeight(),
358 nextPiece.shape());
359 }
360 nextPieceLabel->setPixmap(pixmap);
361//! [32] //! [33]
362}
363//! [33]
364
365//! [34]
366bool TetrixBoard::tryMove(const TetrixPiece &newPiece, int newX, int newY)
367{
368 for (int i = 0; i < 4; ++i) {
369 int x = newX + newPiece.x(i);
370 int y = newY - newPiece.y(i);
371 if (x < 0 || x >= BoardWidth || y < 0 || y >= BoardHeight)
372 return false;
373 if (shapeAt(x, y) != NoShape)
374 return false;
375 }
376//! [34]
377
378//! [35]
379 curPiece = newPiece;
380 curX = newX;
381 curY = newY;
382 update();
383 return true;
384}
385//! [35]
386
387//! [36]
388void TetrixBoard::drawSquare(QPainter &painter, int x, int y, TetrixShape shape)
389{
390 static const QRgb colorTable[8] = {
391 0x000000, 0xCC6666, 0x66CC66, 0x6666CC,
392 0xCCCC66, 0xCC66CC, 0x66CCCC, 0xDAAA00
393 };
394
395 QColor color = colorTable[int(shape)];
396 painter.fillRect(x + 1, y + 1, squareWidth() - 2, squareHeight() - 2,
397 color);
398
399 painter.setPen(color.light());
400 painter.drawLine(x, y + squareHeight() - 1, x, y);
401 painter.drawLine(x, y, x + squareWidth() - 1, y);
402
403 painter.setPen(color.dark());
404 painter.drawLine(x + 1, y + squareHeight() - 1,
405 x + squareWidth() - 1, y + squareHeight() - 1);
406 painter.drawLine(x + squareWidth() - 1, y + squareHeight() - 1,
407 x + squareWidth() - 1, y + 1);
408}
409//! [36]
Note: See TracBrowser for help on using the repository browser.