~oif-team/ubuntu/natty/qt4-x11/xi2.1

« back to all changes in this revision

Viewing changes to examples/widgets/tetrix/tetrixboard.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Adam Conrad
  • Date: 2005-08-24 04:09:09 UTC
  • Revision ID: james.westby@ubuntu.com-20050824040909-xmxe9jfr4a0w5671
Tags: upstream-4.0.0
ImportĀ upstreamĀ versionĀ 4.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************************
 
2
**
 
3
** Copyright (C) 2004-2005 Trolltech AS. All rights reserved.
 
4
**
 
5
** This file is part of the example classes of the Qt Toolkit.
 
6
**
 
7
** This file may be distributed under the terms of the Q Public License
 
8
** as defined by Trolltech AS of Norway and appearing in the file
 
9
** LICENSE.QPL included in the packaging of this file.
 
10
**
 
11
** This file may be distributed and/or modified under the terms of the
 
12
** GNU General Public License version 2 as published by the Free Software
 
13
** Foundation and appearing in the file LICENSE.GPL included in the
 
14
** packaging of this file.
 
15
**
 
16
** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
 
17
**   information about Qt Commercial License Agreements.
 
18
** See http://www.trolltech.com/qpl/ for QPL licensing information.
 
19
** See http://www.trolltech.com/gpl/ for GPL licensing information.
 
20
**
 
21
** Contact info@trolltech.com if any conditions of this licensing are
 
22
** not clear to you.
 
23
**
 
24
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 
25
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 
26
**
 
27
****************************************************************************/
 
28
 
 
29
#include <QtGui>
 
30
 
 
31
#include "tetrixboard.h"
 
32
 
 
33
TetrixBoard::TetrixBoard(QWidget *parent)
 
34
    : QFrame(parent)
 
35
{
 
36
    setFrameStyle(QFrame::Panel | QFrame::Sunken);
 
37
    setFocusPolicy(Qt::StrongFocus);
 
38
    isStarted = false;
 
39
    isPaused = false;
 
40
    clearBoard();
 
41
 
 
42
    nextPiece.setRandomShape();
 
43
}
 
44
 
 
45
void TetrixBoard::setNextPieceLabel(QLabel *label)
 
46
{
 
47
    nextPieceLabel = label;
 
48
}
 
49
 
 
50
QSize TetrixBoard::sizeHint() const
 
51
{
 
52
    return QSize(BoardWidth * 15 + frameWidth() * 2,
 
53
                 BoardHeight * 15 + frameWidth() * 2);
 
54
}
 
55
 
 
56
QSize TetrixBoard::minimumSizeHint() const
 
57
{
 
58
    return QSize(BoardWidth * 5 + frameWidth() * 2,
 
59
                 BoardHeight * 5 + frameWidth() * 2);
 
60
}
 
61
 
 
62
void TetrixBoard::start()
 
63
{
 
64
    if (isPaused)
 
65
        return;
 
66
 
 
67
    isStarted = true;
 
68
    isWaitingAfterLine = false;
 
69
    numLinesRemoved = 0;
 
70
    numPiecesDropped = 0;
 
71
    score = 0;
 
72
    level = 1;
 
73
    clearBoard();
 
74
 
 
75
    emit linesRemovedChanged(numLinesRemoved);
 
76
    emit scoreChanged(score);
 
77
    emit levelChanged(level);
 
78
 
 
79
    newPiece();
 
80
    timer.start(timeoutTime(), this);
 
81
}
 
82
 
 
83
void TetrixBoard::pause()
 
84
{
 
85
    if (!isStarted)
 
86
        return;
 
87
 
 
88
    isPaused = !isPaused;
 
89
    if (isPaused) {
 
90
        timer.stop();
 
91
    } else {
 
92
        timer.start(timeoutTime(), this);
 
93
    }
 
94
    update();
 
95
}
 
96
 
 
97
void TetrixBoard::paintEvent(QPaintEvent *)
 
98
{
 
99
    QPainter painter(this);
 
100
    QRect rect = contentsRect();
 
101
 
 
102
    drawFrame(&painter);
 
103
 
 
104
    if (isPaused) {
 
105
        painter.drawText(rect, Qt::AlignCenter, tr("Pause"));
 
106
        return;
 
107
    }
 
108
 
 
109
    int boardTop = rect.bottom() - BoardHeight*squareHeight();
 
110
 
 
111
    for (int i = 0; i < BoardHeight; ++i) {
 
112
        for (int j = 0; j < BoardWidth; ++j) {
 
113
            TetrixShape shape = shapeAt(j, BoardHeight - i - 1);
 
114
            if (shape != NoShape)
 
115
                drawSquare(painter, rect.left() + j * squareWidth(),
 
116
                           boardTop + i * squareHeight(), shape);
 
117
        }
 
118
    }
 
119
 
 
120
    if (curPiece.shape() != NoShape) {
 
121
        for (int i = 0; i < 4; ++i) {
 
122
            int x = curX + curPiece.x(i);
 
123
            int y = curY - curPiece.y(i);
 
124
            drawSquare(painter, rect.left() + x * squareWidth(),
 
125
                       boardTop + (BoardHeight - y - 1) * squareHeight(),
 
126
                       curPiece.shape());
 
127
        }
 
128
    }
 
129
}
 
130
 
 
131
void TetrixBoard::keyPressEvent(QKeyEvent *event)
 
132
{
 
133
    if (!isStarted || isPaused || curPiece.shape() == NoShape) {
 
134
        QWidget::keyPressEvent(event);
 
135
        return;
 
136
    }
 
137
 
 
138
    switch (event->key()) {
 
139
    case Qt::Key_Left:
 
140
        tryMove(curPiece, curX - 1, curY);
 
141
        break;
 
142
    case Qt::Key_Right:
 
143
        tryMove(curPiece, curX + 1, curY);
 
144
        break;
 
145
    case Qt::Key_Down:
 
146
        tryMove(curPiece.rotatedRight(), curX, curY);
 
147
        break;
 
148
    case Qt::Key_Up:
 
149
        tryMove(curPiece.rotatedLeft(), curX, curY);
 
150
        break;
 
151
    case Qt::Key_Space:
 
152
        dropDown();
 
153
        break;
 
154
    case Qt::Key_D:
 
155
        oneLineDown();
 
156
        break;
 
157
    default:
 
158
        QWidget::keyPressEvent(event);
 
159
    }
 
160
}
 
161
 
 
162
void TetrixBoard::timerEvent(QTimerEvent *event)
 
163
{
 
164
    if (event->timerId() == timer.timerId()) {
 
165
        if (isWaitingAfterLine) {
 
166
            isWaitingAfterLine = false;
 
167
            newPiece();
 
168
            timer.start(timeoutTime(), this);
 
169
        } else {
 
170
            oneLineDown();
 
171
        }
 
172
    } else {
 
173
        QFrame::timerEvent(event);
 
174
    }
 
175
}
 
176
 
 
177
void TetrixBoard::clearBoard()
 
178
{
 
179
    for (int i = 0; i < BoardHeight * BoardWidth; ++i)
 
180
        board[i] = NoShape;
 
181
}
 
182
 
 
183
void TetrixBoard::dropDown()
 
184
{
 
185
    int dropHeight = 0;
 
186
    int newY = curY;
 
187
    while (newY > 0) {
 
188
        if (!tryMove(curPiece, curX, newY - 1))
 
189
            break;
 
190
        --newY;
 
191
        ++dropHeight;
 
192
    }
 
193
    pieceDropped(dropHeight);
 
194
}
 
195
 
 
196
void TetrixBoard::oneLineDown()
 
197
{
 
198
    if (!tryMove(curPiece, curX, curY - 1))
 
199
        pieceDropped(0);
 
200
}
 
201
 
 
202
void TetrixBoard::pieceDropped(int dropHeight)
 
203
{
 
204
    for (int i = 0; i < 4; ++i) {
 
205
        int x = curX + curPiece.x(i);
 
206
        int y = curY - curPiece.y(i);
 
207
        shapeAt(x, y) = curPiece.shape();
 
208
    }
 
209
 
 
210
    ++numPiecesDropped;
 
211
    if (numPiecesDropped % 25 == 0) {
 
212
        ++level;
 
213
        timer.start(timeoutTime(), this);
 
214
        emit levelChanged(level);
 
215
    }
 
216
 
 
217
    score += dropHeight + 7;
 
218
    emit scoreChanged(score);
 
219
    removeFullLines();
 
220
 
 
221
    if (!isWaitingAfterLine)
 
222
        newPiece();
 
223
}
 
224
 
 
225
void TetrixBoard::removeFullLines()
 
226
{
 
227
    int numFullLines = 0;
 
228
 
 
229
    for (int i = BoardHeight - 1; i >= 0; --i) {
 
230
        bool lineIsFull = true;
 
231
 
 
232
        for (int j = 0; j < BoardWidth; ++j) {
 
233
            if (shapeAt(j, i) == NoShape) {
 
234
                lineIsFull = false;
 
235
                break;
 
236
            }
 
237
        }
 
238
 
 
239
        if (lineIsFull) {
 
240
            ++numFullLines;
 
241
            for (int k = i; k < BoardHeight - 1; ++k) {
 
242
                for (int j = 0; j < BoardWidth; ++j)
 
243
                    shapeAt(j, k) = shapeAt(j, k + 1);
 
244
            }
 
245
            for (int j = 0; j < BoardWidth; ++j)
 
246
                shapeAt(j, BoardHeight - 1) = NoShape;
 
247
        }
 
248
    }
 
249
 
 
250
    if (numFullLines > 0) {
 
251
        numLinesRemoved += numFullLines;
 
252
        score += 10 * numFullLines;
 
253
        emit linesRemovedChanged(numLinesRemoved);
 
254
        emit scoreChanged(score);
 
255
 
 
256
        timer.start(500, this);
 
257
        isWaitingAfterLine = true;
 
258
        curPiece.setShape(NoShape);
 
259
        update();
 
260
    }
 
261
}
 
262
 
 
263
void TetrixBoard::newPiece()
 
264
{
 
265
    curPiece = nextPiece;
 
266
    nextPiece.setRandomShape();
 
267
    showNextPiece();
 
268
    curX = BoardWidth / 2 + 1;
 
269
    curY = BoardHeight - 1 + curPiece.minY();
 
270
 
 
271
    if (!tryMove(curPiece, curX, curY)) {
 
272
        curPiece.setShape(NoShape);
 
273
        timer.stop();
 
274
        isStarted = false;
 
275
    }
 
276
}
 
277
 
 
278
void TetrixBoard::showNextPiece()
 
279
{
 
280
    if (!nextPieceLabel)
 
281
        return;
 
282
 
 
283
    int dx = nextPiece.maxX() - nextPiece.minX() + 1;
 
284
    int dy = nextPiece.maxY() - nextPiece.minY() + 1;
 
285
 
 
286
    QPixmap pixmap(dx * squareWidth(), dy * squareHeight());
 
287
    QPainter painter(&pixmap);
 
288
    painter.fillRect(pixmap.rect(), nextPieceLabel->palette().background());
 
289
 
 
290
    for (int i = 0; i < 4; ++i) {
 
291
        int x = nextPiece.x(i) - nextPiece.minX();
 
292
        int y = nextPiece.y(i) - nextPiece.minY();
 
293
        drawSquare(painter, x * squareWidth(), y * squareHeight(),
 
294
                   nextPiece.shape());
 
295
    }
 
296
    nextPieceLabel->setPixmap(pixmap);
 
297
}
 
298
 
 
299
bool TetrixBoard::tryMove(const TetrixPiece &newPiece, int newX, int newY)
 
300
{
 
301
    for (int i = 0; i < 4; ++i) {
 
302
        int x = newX + newPiece.x(i);
 
303
        int y = newY - newPiece.y(i);
 
304
        if (x < 0 || x >= BoardWidth || y < 0 || y >= BoardHeight)
 
305
            return false;
 
306
        if (shapeAt(x, y) != NoShape)
 
307
            return false;
 
308
    }
 
309
 
 
310
    curPiece = newPiece;
 
311
    curX = newX;
 
312
    curY = newY;
 
313
    update();
 
314
    return true;
 
315
}
 
316
 
 
317
void TetrixBoard::drawSquare(QPainter &painter, int x, int y, TetrixShape shape)
 
318
{
 
319
    static const QRgb colorTable[8] = {
 
320
        0x000000, 0xCC6666, 0x66CC66, 0x6666CC,
 
321
        0xCCCC66, 0xCC66CC, 0x66CCCC, 0xDAAA00
 
322
    };
 
323
 
 
324
    QColor color = colorTable[int(shape)];
 
325
    painter.fillRect(x + 1, y + 1, squareWidth() - 2, squareHeight() - 2,
 
326
                     color);
 
327
 
 
328
    painter.setPen(color.light());
 
329
    painter.drawLine(x, y + squareHeight() - 1, x, y);
 
330
    painter.drawLine(x, y, x + squareWidth() - 1, y);
 
331
 
 
332
    painter.setPen(color.dark());
 
333
    painter.drawLine(x + 1, y + squareHeight() - 1,
 
334
                     x + squareWidth() - 1, y + squareHeight() - 1);
 
335
    painter.drawLine(x + squareWidth() - 1, y + squareHeight() - 1,
 
336
                     x + squareWidth() - 1, y + 1);
 
337
}