diff options
Diffstat (limited to 'examples/widgets/tetrix/tetrixboard.cpp')
-rw-r--r-- | examples/widgets/tetrix/tetrixboard.cpp | 409 |
1 files changed, 409 insertions, 0 deletions
diff --git a/examples/widgets/tetrix/tetrixboard.cpp b/examples/widgets/tetrix/tetrixboard.cpp new file mode 100644 index 0000000..e8ef4bf --- /dev/null +++ b/examples/widgets/tetrix/tetrixboard.cpp @@ -0,0 +1,409 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtGui> + +#include "tetrixboard.h" + +//! [0] +TetrixBoard::TetrixBoard(QWidget *parent) + : QFrame(parent) +{ + setFrameStyle(QFrame::Panel | QFrame::Sunken); + setFocusPolicy(Qt::StrongFocus); + isStarted = false; + isPaused = false; + clearBoard(); + + nextPiece.setRandomShape(); +} +//! [0] + +//! [1] +void TetrixBoard::setNextPieceLabel(QLabel *label) +{ + nextPieceLabel = label; +} +//! [1] + +//! [2] +QSize TetrixBoard::sizeHint() const +{ + return QSize(BoardWidth * 15 + frameWidth() * 2, + BoardHeight * 15 + frameWidth() * 2); +} + +QSize TetrixBoard::minimumSizeHint() const +//! [2] //! [3] +{ + return QSize(BoardWidth * 5 + frameWidth() * 2, + BoardHeight * 5 + frameWidth() * 2); +} +//! [3] + +//! [4] +void TetrixBoard::start() +{ + if (isPaused) + return; + + isStarted = true; + isWaitingAfterLine = false; + numLinesRemoved = 0; + numPiecesDropped = 0; + score = 0; + level = 1; + clearBoard(); + + emit linesRemovedChanged(numLinesRemoved); + emit scoreChanged(score); + emit levelChanged(level); + + newPiece(); + timer.start(timeoutTime(), this); +} +//! [4] + +//! [5] +void TetrixBoard::pause() +{ + if (!isStarted) + return; + + isPaused = !isPaused; + if (isPaused) { + timer.stop(); + } else { + timer.start(timeoutTime(), this); + } + update(); +//! [5] //! [6] +} +//! [6] + +//! [7] +void TetrixBoard::paintEvent(QPaintEvent *event) +{ + QFrame::paintEvent(event); + + QPainter painter(this); + QRect rect = contentsRect(); +//! [7] + + if (isPaused) { + painter.drawText(rect, Qt::AlignCenter, tr("Pause")); + return; + } + +//! [8] + int boardTop = rect.bottom() - BoardHeight*squareHeight(); + + for (int i = 0; i < BoardHeight; ++i) { + for (int j = 0; j < BoardWidth; ++j) { + TetrixShape shape = shapeAt(j, BoardHeight - i - 1); + if (shape != NoShape) + drawSquare(painter, rect.left() + j * squareWidth(), + boardTop + i * squareHeight(), shape); + } +//! [8] //! [9] + } +//! [9] + +//! [10] + if (curPiece.shape() != NoShape) { + for (int i = 0; i < 4; ++i) { + int x = curX + curPiece.x(i); + int y = curY - curPiece.y(i); + drawSquare(painter, rect.left() + x * squareWidth(), + boardTop + (BoardHeight - y - 1) * squareHeight(), + curPiece.shape()); + } +//! [10] //! [11] + } +//! [11] //! [12] +} +//! [12] + +//! [13] +void TetrixBoard::keyPressEvent(QKeyEvent *event) +{ + if (!isStarted || isPaused || curPiece.shape() == NoShape) { + QFrame::keyPressEvent(event); + return; + } +//! [13] + +//! [14] + switch (event->key()) { + case Qt::Key_Left: + tryMove(curPiece, curX - 1, curY); + break; + case Qt::Key_Right: + tryMove(curPiece, curX + 1, curY); + break; + case Qt::Key_Down: + tryMove(curPiece.rotatedRight(), curX, curY); + break; + case Qt::Key_Up: + tryMove(curPiece.rotatedLeft(), curX, curY); + break; + case Qt::Key_Space: + dropDown(); + break; + case Qt::Key_D: + oneLineDown(); + break; + default: + QFrame::keyPressEvent(event); + } +//! [14] +} + +//! [15] +void TetrixBoard::timerEvent(QTimerEvent *event) +{ + if (event->timerId() == timer.timerId()) { + if (isWaitingAfterLine) { + isWaitingAfterLine = false; + newPiece(); + timer.start(timeoutTime(), this); + } else { + oneLineDown(); + } + } else { + QFrame::timerEvent(event); +//! [15] //! [16] + } +//! [16] //! [17] +} +//! [17] + +//! [18] +void TetrixBoard::clearBoard() +{ + for (int i = 0; i < BoardHeight * BoardWidth; ++i) + board[i] = NoShape; +} +//! [18] + +//! [19] +void TetrixBoard::dropDown() +{ + int dropHeight = 0; + int newY = curY; + while (newY > 0) { + if (!tryMove(curPiece, curX, newY - 1)) + break; + --newY; + ++dropHeight; + } + pieceDropped(dropHeight); +//! [19] //! [20] +} +//! [20] + +//! [21] +void TetrixBoard::oneLineDown() +{ + if (!tryMove(curPiece, curX, curY - 1)) + pieceDropped(0); +} +//! [21] + +//! [22] +void TetrixBoard::pieceDropped(int dropHeight) +{ + for (int i = 0; i < 4; ++i) { + int x = curX + curPiece.x(i); + int y = curY - curPiece.y(i); + shapeAt(x, y) = curPiece.shape(); + } + + ++numPiecesDropped; + if (numPiecesDropped % 25 == 0) { + ++level; + timer.start(timeoutTime(), this); + emit levelChanged(level); + } + + score += dropHeight + 7; + emit scoreChanged(score); + removeFullLines(); + + if (!isWaitingAfterLine) + newPiece(); +//! [22] //! [23] +} +//! [23] + +//! [24] +void TetrixBoard::removeFullLines() +{ + int numFullLines = 0; + + for (int i = BoardHeight - 1; i >= 0; --i) { + bool lineIsFull = true; + + for (int j = 0; j < BoardWidth; ++j) { + if (shapeAt(j, i) == NoShape) { + lineIsFull = false; + break; + } + } + + if (lineIsFull) { +//! [24] //! [25] + ++numFullLines; + for (int k = i; k < BoardHeight - 1; ++k) { + for (int j = 0; j < BoardWidth; ++j) + shapeAt(j, k) = shapeAt(j, k + 1); + } +//! [25] //! [26] + for (int j = 0; j < BoardWidth; ++j) + shapeAt(j, BoardHeight - 1) = NoShape; + } +//! [26] //! [27] + } +//! [27] + +//! [28] + if (numFullLines > 0) { + numLinesRemoved += numFullLines; + score += 10 * numFullLines; + emit linesRemovedChanged(numLinesRemoved); + emit scoreChanged(score); + + timer.start(500, this); + isWaitingAfterLine = true; + curPiece.setShape(NoShape); + update(); + } +//! [28] //! [29] +} +//! [29] + +//! [30] +void TetrixBoard::newPiece() +{ + curPiece = nextPiece; + nextPiece.setRandomShape(); + showNextPiece(); + curX = BoardWidth / 2 + 1; + curY = BoardHeight - 1 + curPiece.minY(); + + if (!tryMove(curPiece, curX, curY)) { + curPiece.setShape(NoShape); + timer.stop(); + isStarted = false; + } +//! [30] //! [31] +} +//! [31] + +//! [32] +void TetrixBoard::showNextPiece() +{ + if (!nextPieceLabel) + return; + + int dx = nextPiece.maxX() - nextPiece.minX() + 1; + int dy = nextPiece.maxY() - nextPiece.minY() + 1; + + QPixmap pixmap(dx * squareWidth(), dy * squareHeight()); + QPainter painter(&pixmap); + painter.fillRect(pixmap.rect(), nextPieceLabel->palette().background()); + + for (int i = 0; i < 4; ++i) { + int x = nextPiece.x(i) - nextPiece.minX(); + int y = nextPiece.y(i) - nextPiece.minY(); + drawSquare(painter, x * squareWidth(), y * squareHeight(), + nextPiece.shape()); + } + nextPieceLabel->setPixmap(pixmap); +//! [32] //! [33] +} +//! [33] + +//! [34] +bool TetrixBoard::tryMove(const TetrixPiece &newPiece, int newX, int newY) +{ + for (int i = 0; i < 4; ++i) { + int x = newX + newPiece.x(i); + int y = newY - newPiece.y(i); + if (x < 0 || x >= BoardWidth || y < 0 || y >= BoardHeight) + return false; + if (shapeAt(x, y) != NoShape) + return false; + } +//! [34] + +//! [35] + curPiece = newPiece; + curX = newX; + curY = newY; + update(); + return true; +} +//! [35] + +//! [36] +void TetrixBoard::drawSquare(QPainter &painter, int x, int y, TetrixShape shape) +{ + static const QRgb colorTable[8] = { + 0x000000, 0xCC6666, 0x66CC66, 0x6666CC, + 0xCCCC66, 0xCC66CC, 0x66CCCC, 0xDAAA00 + }; + + QColor color = colorTable[int(shape)]; + painter.fillRect(x + 1, y + 1, squareWidth() - 2, squareHeight() - 2, + color); + + painter.setPen(color.light()); + painter.drawLine(x, y + squareHeight() - 1, x, y); + painter.drawLine(x, y, x + squareWidth() - 1, y); + + painter.setPen(color.dark()); + painter.drawLine(x + 1, y + squareHeight() - 1, + x + squareWidth() - 1, y + squareHeight() - 1); + painter.drawLine(x + squareWidth() - 1, y + squareHeight() - 1, + x + squareWidth() - 1, y + 1); +} +//! [36] |