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

Last change on this file since 1165 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 9.8 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 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:BSD$
10** You may use this file under the terms of the BSD license as follows:
11**
12** "Redistribution and use in source and binary forms, with or without
13** modification, are permitted provided that the following conditions are
14** met:
15** * Redistributions of source code must retain the above copyright
16** notice, this list of conditions and the following disclaimer.
17** * Redistributions in binary form must reproduce the above copyright
18** notice, this list of conditions and the following disclaimer in
19** the documentation and/or other materials provided with the
20** distribution.
21** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
22** the names of its contributors may be used to endorse or promote
23** products derived from this software without specific prior written
24** permission.
25**
26** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
29** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
30** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
36** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
37** $QT_END_LICENSE$
38**
39****************************************************************************/
40
41#include <QtGui>
42
43#include "tetrixboard.h"
44
45//! [0]
46TetrixBoard::TetrixBoard(QWidget *parent)
47 : QFrame(parent)
48{
49 setFrameStyle(QFrame::Panel | QFrame::Sunken);
50 setFocusPolicy(Qt::StrongFocus);
51 isStarted = false;
52 isPaused = false;
53 clearBoard();
54
55 nextPiece.setRandomShape();
56}
57//! [0]
58
59//! [1]
60void TetrixBoard::setNextPieceLabel(QLabel *label)
61{
62 nextPieceLabel = label;
63}
64//! [1]
65
66//! [2]
67QSize TetrixBoard::sizeHint() const
68{
69 return QSize(BoardWidth * 15 + frameWidth() * 2,
70 BoardHeight * 15 + frameWidth() * 2);
71}
72
73QSize TetrixBoard::minimumSizeHint() const
74//! [2] //! [3]
75{
76 return QSize(BoardWidth * 5 + frameWidth() * 2,
77 BoardHeight * 5 + frameWidth() * 2);
78}
79//! [3]
80
81//! [4]
82void TetrixBoard::start()
83{
84 if (isPaused)
85 return;
86
87 isStarted = true;
88 isWaitingAfterLine = false;
89 numLinesRemoved = 0;
90 numPiecesDropped = 0;
91 score = 0;
92 level = 1;
93 clearBoard();
94
95 emit linesRemovedChanged(numLinesRemoved);
96 emit scoreChanged(score);
97 emit levelChanged(level);
98
99 newPiece();
100 timer.start(timeoutTime(), this);
101}
102//! [4]
103
104//! [5]
105void TetrixBoard::pause()
106{
107 if (!isStarted)
108 return;
109
110 isPaused = !isPaused;
111 if (isPaused) {
112 timer.stop();
113 } else {
114 timer.start(timeoutTime(), this);
115 }
116 update();
117//! [5] //! [6]
118}
119//! [6]
120
121//! [7]
122void TetrixBoard::paintEvent(QPaintEvent *event)
123{
124 QFrame::paintEvent(event);
125
126 QPainter painter(this);
127 QRect rect = contentsRect();
128//! [7]
129
130 if (isPaused) {
131 painter.drawText(rect, Qt::AlignCenter, tr("Pause"));
132 return;
133 }
134
135//! [8]
136 int boardTop = rect.bottom() - BoardHeight*squareHeight();
137
138 for (int i = 0; i < BoardHeight; ++i) {
139 for (int j = 0; j < BoardWidth; ++j) {
140 TetrixShape shape = shapeAt(j, BoardHeight - i - 1);
141 if (shape != NoShape)
142 drawSquare(painter, rect.left() + j * squareWidth(),
143 boardTop + i * squareHeight(), shape);
144 }
145//! [8] //! [9]
146 }
147//! [9]
148
149//! [10]
150 if (curPiece.shape() != NoShape) {
151 for (int i = 0; i < 4; ++i) {
152 int x = curX + curPiece.x(i);
153 int y = curY - curPiece.y(i);
154 drawSquare(painter, rect.left() + x * squareWidth(),
155 boardTop + (BoardHeight - y - 1) * squareHeight(),
156 curPiece.shape());
157 }
158//! [10] //! [11]
159 }
160//! [11] //! [12]
161}
162//! [12]
163
164//! [13]
165void TetrixBoard::keyPressEvent(QKeyEvent *event)
166{
167 if (!isStarted || isPaused || curPiece.shape() == NoShape) {
168 QFrame::keyPressEvent(event);
169 return;
170 }
171//! [13]
172
173//! [14]
174 switch (event->key()) {
175 case Qt::Key_Left:
176 tryMove(curPiece, curX - 1, curY);
177 break;
178 case Qt::Key_Right:
179 tryMove(curPiece, curX + 1, curY);
180 break;
181 case Qt::Key_Down:
182 tryMove(curPiece.rotatedRight(), curX, curY);
183 break;
184 case Qt::Key_Up:
185 tryMove(curPiece.rotatedLeft(), curX, curY);
186 break;
187 case Qt::Key_Space:
188 dropDown();
189 break;
190 case Qt::Key_D:
191 oneLineDown();
192 break;
193 default:
194 QFrame::keyPressEvent(event);
195 }
196//! [14]
197}
198
199//! [15]
200void TetrixBoard::timerEvent(QTimerEvent *event)
201{
202 if (event->timerId() == timer.timerId()) {
203 if (isWaitingAfterLine) {
204 isWaitingAfterLine = false;
205 newPiece();
206 timer.start(timeoutTime(), this);
207 } else {
208 oneLineDown();
209 }
210 } else {
211 QFrame::timerEvent(event);
212//! [15] //! [16]
213 }
214//! [16] //! [17]
215}
216//! [17]
217
218//! [18]
219void TetrixBoard::clearBoard()
220{
221 for (int i = 0; i < BoardHeight * BoardWidth; ++i)
222 board[i] = NoShape;
223}
224//! [18]
225
226//! [19]
227void TetrixBoard::dropDown()
228{
229 int dropHeight = 0;
230 int newY = curY;
231 while (newY > 0) {
232 if (!tryMove(curPiece, curX, newY - 1))
233 break;
234 --newY;
235 ++dropHeight;
236 }
237 pieceDropped(dropHeight);
238//! [19] //! [20]
239}
240//! [20]
241
242//! [21]
243void TetrixBoard::oneLineDown()
244{
245 if (!tryMove(curPiece, curX, curY - 1))
246 pieceDropped(0);
247}
248//! [21]
249
250//! [22]
251void TetrixBoard::pieceDropped(int dropHeight)
252{
253 for (int i = 0; i < 4; ++i) {
254 int x = curX + curPiece.x(i);
255 int y = curY - curPiece.y(i);
256 shapeAt(x, y) = curPiece.shape();
257 }
258
259 ++numPiecesDropped;
260 if (numPiecesDropped % 25 == 0) {
261 ++level;
262 timer.start(timeoutTime(), this);
263 emit levelChanged(level);
264 }
265
266 score += dropHeight + 7;
267 emit scoreChanged(score);
268 removeFullLines();
269
270 if (!isWaitingAfterLine)
271 newPiece();
272//! [22] //! [23]
273}
274//! [23]
275
276//! [24]
277void TetrixBoard::removeFullLines()
278{
279 int numFullLines = 0;
280
281 for (int i = BoardHeight - 1; i >= 0; --i) {
282 bool lineIsFull = true;
283
284 for (int j = 0; j < BoardWidth; ++j) {
285 if (shapeAt(j, i) == NoShape) {
286 lineIsFull = false;
287 break;
288 }
289 }
290
291 if (lineIsFull) {
292//! [24] //! [25]
293 ++numFullLines;
294 for (int k = i; k < BoardHeight - 1; ++k) {
295 for (int j = 0; j < BoardWidth; ++j)
296 shapeAt(j, k) = shapeAt(j, k + 1);
297 }
298//! [25] //! [26]
299 for (int j = 0; j < BoardWidth; ++j)
300 shapeAt(j, BoardHeight - 1) = NoShape;
301 }
302//! [26] //! [27]
303 }
304//! [27]
305
306//! [28]
307 if (numFullLines > 0) {
308 numLinesRemoved += numFullLines;
309 score += 10 * numFullLines;
310 emit linesRemovedChanged(numLinesRemoved);
311 emit scoreChanged(score);
312
313 timer.start(500, this);
314 isWaitingAfterLine = true;
315 curPiece.setShape(NoShape);
316 update();
317 }
318//! [28] //! [29]
319}
320//! [29]
321
322//! [30]
323void TetrixBoard::newPiece()
324{
325 curPiece = nextPiece;
326 nextPiece.setRandomShape();
327 showNextPiece();
328 curX = BoardWidth / 2 + 1;
329 curY = BoardHeight - 1 + curPiece.minY();
330
331 if (!tryMove(curPiece, curX, curY)) {
332 curPiece.setShape(NoShape);
333 timer.stop();
334 isStarted = false;
335 }
336//! [30] //! [31]
337}
338//! [31]
339
340//! [32]
341void TetrixBoard::showNextPiece()
342{
343 if (!nextPieceLabel)
344 return;
345
346 int dx = nextPiece.maxX() - nextPiece.minX() + 1;
347 int dy = nextPiece.maxY() - nextPiece.minY() + 1;
348
349 QPixmap pixmap(dx * squareWidth(), dy * squareHeight());
350 QPainter painter(&pixmap);
351 painter.fillRect(pixmap.rect(), nextPieceLabel->palette().background());
352
353 for (int i = 0; i < 4; ++i) {
354 int x = nextPiece.x(i) - nextPiece.minX();
355 int y = nextPiece.y(i) - nextPiece.minY();
356 drawSquare(painter, x * squareWidth(), y * squareHeight(),
357 nextPiece.shape());
358 }
359 nextPieceLabel->setPixmap(pixmap);
360//! [32] //! [33]
361}
362//! [33]
363
364//! [34]
365bool TetrixBoard::tryMove(const TetrixPiece &newPiece, int newX, int newY)
366{
367 for (int i = 0; i < 4; ++i) {
368 int x = newX + newPiece.x(i);
369 int y = newY - newPiece.y(i);
370 if (x < 0 || x >= BoardWidth || y < 0 || y >= BoardHeight)
371 return false;
372 if (shapeAt(x, y) != NoShape)
373 return false;
374 }
375//! [34]
376
377//! [35]
378 curPiece = newPiece;
379 curX = newX;
380 curY = newY;
381 update();
382 return true;
383}
384//! [35]
385
386//! [36]
387void TetrixBoard::drawSquare(QPainter &painter, int x, int y, TetrixShape shape)
388{
389 static const QRgb colorTable[8] = {
390 0x000000, 0xCC6666, 0x66CC66, 0x6666CC,
391 0xCCCC66, 0xCC66CC, 0x66CCCC, 0xDAAA00
392 };
393
394 QColor color = colorTable[int(shape)];
395 painter.fillRect(x + 1, y + 1, squareWidth() - 2, squareHeight() - 2,
396 color);
397
398 painter.setPen(color.light());
399 painter.drawLine(x, y + squareHeight() - 1, x, y);
400 painter.drawLine(x, y, x + squareWidth() - 1, y);
401
402 painter.setPen(color.dark());
403 painter.drawLine(x + 1, y + squareHeight() - 1,
404 x + squareWidth() - 1, y + squareHeight() - 1);
405 painter.drawLine(x + squareWidth() - 1, y + squareHeight() - 1,
406 x + squareWidth() - 1, y + 1);
407}
408//! [36]
Note: See TracBrowser for help on using the repository browser.