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 documentation 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 | /*!
|
---|
43 | \example widgets/tetrix
|
---|
44 | \title Tetrix Example
|
---|
45 |
|
---|
46 | The Tetrix example is a Qt version of the classic Tetrix game.
|
---|
47 |
|
---|
48 | \image tetrix-example.png
|
---|
49 |
|
---|
50 | The object of the game is to stack pieces dropped from the top of the
|
---|
51 | playing area so that they fill entire rows at the bottom of the playing area.
|
---|
52 |
|
---|
53 | When a row is filled, all the blocks on that row are removed, the player earns
|
---|
54 | a number of points, and the pieces above are moved down to occupy that row.
|
---|
55 | If more than one row is filled, the blocks on each row are removed, and the
|
---|
56 | player earns extra points.
|
---|
57 |
|
---|
58 | The \gui{Left} cursor key moves the current piece one space to the left, the
|
---|
59 | \gui{Right} cursor key moves it one space to the right, the \gui{Up} cursor
|
---|
60 | key rotates the piece counter-clockwise by 90 degrees, and the \gui{Down}
|
---|
61 | cursor key rotates the piece clockwise by 90 degrees.
|
---|
62 |
|
---|
63 | To avoid waiting for a piece to fall to the bottom of the board, press \gui{D}
|
---|
64 | to immediately move the piece down by one row, or press the \gui{Space} key to
|
---|
65 | drop it as close to the bottom of the board as possible.
|
---|
66 |
|
---|
67 | This example shows how a simple game can be created using only three classes:
|
---|
68 |
|
---|
69 | \list
|
---|
70 | \o The \c TetrixWindow class is used to display the player's score, number of
|
---|
71 | lives, and information about the next piece to appear.
|
---|
72 | \o The \c TetrixBoard class contains the game logic, handles keyboard input, and
|
---|
73 | displays the pieces on the playing area.
|
---|
74 | \o The \c TetrixPiece class contains information about each piece.
|
---|
75 | \endlist
|
---|
76 |
|
---|
77 | In this approach, the \c TetrixBoard class is the most complex class, since it
|
---|
78 | handles the game logic and rendering. One benefit of this is that the
|
---|
79 | \c TetrixWindow and \c TetrixPiece classes are very simple and contain only a
|
---|
80 | minimum of code.
|
---|
81 |
|
---|
82 | \section1 TetrixWindow Class Definition
|
---|
83 |
|
---|
84 | The \c TetrixWindow class is used to display the game information and contains
|
---|
85 | the playing area:
|
---|
86 |
|
---|
87 | \snippet examples/widgets/tetrix/tetrixwindow.h 0
|
---|
88 |
|
---|
89 | We use private member variables for the board, various display widgets, and
|
---|
90 | buttons to allow the user to start a new game, pause the current game, and quit.
|
---|
91 |
|
---|
92 | Although the window inherits QWidget, the constructor does not provide an
|
---|
93 | argument to allow a parent widget to be specified. This is because the window
|
---|
94 | will always be used as a top-level widget.
|
---|
95 |
|
---|
96 | \section1 TetrixWindow Class Implementation
|
---|
97 |
|
---|
98 | The constructor sets up the user interface elements for the game:
|
---|
99 |
|
---|
100 | \snippet examples/widgets/tetrix/tetrixwindow.cpp 0
|
---|
101 |
|
---|
102 | We begin by constructing a \c TetrixBoard instance for the playing area and a
|
---|
103 | label that shows the next piece to be dropped into the playing area; the label
|
---|
104 | is initially empty.
|
---|
105 |
|
---|
106 | Three QLCDNumber objects are used to display the score, number of lives, and
|
---|
107 | lines removed. These initially show default values, and will be filled in
|
---|
108 | when a game begins:
|
---|
109 |
|
---|
110 | \snippet examples/widgets/tetrix/tetrixwindow.cpp 1
|
---|
111 |
|
---|
112 | Three buttons with shortcuts are constructed so that the user can start a
|
---|
113 | new game, pause the current game, and quit the application:
|
---|
114 |
|
---|
115 | \snippet examples/widgets/tetrix/tetrixwindow.cpp 2
|
---|
116 | \snippet examples/widgets/tetrix/tetrixwindow.cpp 3
|
---|
117 |
|
---|
118 | These buttons are configured so that they never receive the keyboard focus;
|
---|
119 | we want the keyboard focus to remain with the \c TetrixBoard instance so that
|
---|
120 | it receives all the keyboard events. Nonetheless, the buttons will still respond
|
---|
121 | to \key{Alt} key shortcuts.
|
---|
122 |
|
---|
123 | We connect \l{QAbstractButton::}{clicked()} signals from the \gui{Start}
|
---|
124 | and \gui{Pause} buttons to the board, and from the \gui{Quit} button to the
|
---|
125 | application's \l{QApplication::}{quit()} slot.
|
---|
126 |
|
---|
127 | \snippet examples/widgets/tetrix/tetrixwindow.cpp 4
|
---|
128 | \snippet examples/widgets/tetrix/tetrixwindow.cpp 5
|
---|
129 |
|
---|
130 | Signals from the board are also connected to the LCD widgets for the purpose of
|
---|
131 | updating the score, number of lives, and lines removed from the playing area.
|
---|
132 |
|
---|
133 | We place the label, LCD widgets, and the board into a QGridLayout
|
---|
134 | along with some labels that we create with the \c createLabel() convenience
|
---|
135 | function:
|
---|
136 |
|
---|
137 | \snippet examples/widgets/tetrix/tetrixwindow.cpp 6
|
---|
138 |
|
---|
139 | Finally, we set the grid layout on the widget, give the window a title, and
|
---|
140 | resize it to an appropriate size.
|
---|
141 |
|
---|
142 | The \c createLabel() convenience function simply creates a new label on the
|
---|
143 | heap, gives it an appropriate alignment, and returns it to the caller:
|
---|
144 |
|
---|
145 | \snippet examples/widgets/tetrix/tetrixwindow.cpp 7
|
---|
146 |
|
---|
147 | Since each label will be used in the widget's layout, it will become a child
|
---|
148 | of the \c TetrixWindow widget and, as a result, it will be deleted when the
|
---|
149 | window is deleted.
|
---|
150 |
|
---|
151 | \section1 TetrixPiece Class Definition
|
---|
152 |
|
---|
153 | The \c TetrixPiece class holds information about a piece in the game's
|
---|
154 | playing area, including its shape, position, and the range of positions it can
|
---|
155 | occupy on the board:
|
---|
156 |
|
---|
157 | \snippet examples/widgets/tetrix/tetrixpiece.h 0
|
---|
158 |
|
---|
159 | Each shape contains four blocks, and these are defined by the \c coords private
|
---|
160 | member variable. Additionally, each piece has a high-level description that is
|
---|
161 | stored internally in the \c pieceShape variable.
|
---|
162 |
|
---|
163 | The constructor is written inline in the definition, and simply ensures that
|
---|
164 | each piece is initially created with no shape. The \c shape() function simply
|
---|
165 | returns the contents of the \c pieceShape variable, and the \c x() and \c y()
|
---|
166 | functions return the x and y-coordinates of any given block in the shape.
|
---|
167 |
|
---|
168 | \section1 TetrixPiece Class Implementation
|
---|
169 |
|
---|
170 | The \c setRandomShape() function is used to select a random shape for a piece:
|
---|
171 |
|
---|
172 | \snippet examples/widgets/tetrix/tetrixpiece.cpp 0
|
---|
173 |
|
---|
174 | For convenience, it simply chooses a random shape from the \c TetrixShape enum
|
---|
175 | and calls the \c setShape() function to perform the task of positioning the
|
---|
176 | blocks.
|
---|
177 |
|
---|
178 | The \c setShape() function uses a look-up table of pieces to associate each
|
---|
179 | shape with an array of block positions:
|
---|
180 |
|
---|
181 | \snippet examples/widgets/tetrix/tetrixpiece.cpp 1
|
---|
182 | \snippet examples/widgets/tetrix/tetrixpiece.cpp 2
|
---|
183 |
|
---|
184 | These positions are read from the table into the piece's own array of positions,
|
---|
185 | and the piece's internal shape information is updated to use the new shape.
|
---|
186 |
|
---|
187 | The \c x() and \c y() functions are implemented inline in the class definition,
|
---|
188 | returning positions defined on a grid that extends horizontally and vertically
|
---|
189 | with coordinates from -2 to 2. Although the predefined coordinates for each
|
---|
190 | piece only vary horizontally from -1 to 1 and vertically from -1 to 2, each
|
---|
191 | piece can be rotated by 90, 180, and 270 degrees.
|
---|
192 |
|
---|
193 | The \c minX() and \c maxX() functions return the minimum and maximum horizontal
|
---|
194 | coordinates occupied by the blocks that make up the piece:
|
---|
195 |
|
---|
196 | \snippet examples/widgets/tetrix/tetrixpiece.cpp 3
|
---|
197 | \snippet examples/widgets/tetrix/tetrixpiece.cpp 4
|
---|
198 |
|
---|
199 | Similarly, the \c minY() and \c maxY() functions return the minimum and maximum
|
---|
200 | vertical coordinates occupied by the blocks:
|
---|
201 |
|
---|
202 | \snippet examples/widgets/tetrix/tetrixpiece.cpp 5
|
---|
203 | \snippet examples/widgets/tetrix/tetrixpiece.cpp 6
|
---|
204 |
|
---|
205 | The \c rotatedLeft() function returns a new piece with the same shape as an
|
---|
206 | existing piece, but rotated counter-clockwise by 90 degrees:
|
---|
207 |
|
---|
208 | \snippet examples/widgets/tetrix/tetrixpiece.cpp 7
|
---|
209 |
|
---|
210 | Similarly, the \c rotatedRight() function returns a new piece with the same
|
---|
211 | shape as an existing piece, but rotated clockwise by 90 degrees:
|
---|
212 |
|
---|
213 | \snippet examples/widgets/tetrix/tetrixpiece.cpp 9
|
---|
214 |
|
---|
215 | These last two functions enable each piece to create rotated copies of itself.
|
---|
216 |
|
---|
217 | \section1 TetrixBoard Class Definition
|
---|
218 |
|
---|
219 | The \c TetrixBoard class inherits from QFrame and contains the game logic and display features:
|
---|
220 |
|
---|
221 | \snippet examples/widgets/tetrix/tetrixboard.h 0
|
---|
222 |
|
---|
223 | Apart from the \c setNextPieceLabel() function and the \c start() and \c pause()
|
---|
224 | public slots, we only provide public functions to reimplement QWidget::sizeHint()
|
---|
225 | and QWidget::minimumSizeHint(). The signals are used to communicate changes to
|
---|
226 | the player's information to the \c TetrixWindow instance.
|
---|
227 |
|
---|
228 | The rest of the functionality is provided by reimplementations of protected event
|
---|
229 | handlers and private functions:
|
---|
230 |
|
---|
231 | \snippet examples/widgets/tetrix/tetrixboard.h 1
|
---|
232 |
|
---|
233 | The board is composed of a fixed-size array whose elements correspond to
|
---|
234 | spaces for individual blocks. Each element in the array contains a \c TetrixShape
|
---|
235 | value corresponding to the type of shape that occupies that element.
|
---|
236 |
|
---|
237 | Each shape on the board will occupy four elements in the array, and these will
|
---|
238 | all contain the enum value that corresponds to the type of the shape.
|
---|
239 |
|
---|
240 | We use a QBasicTimer to control the rate at which pieces fall toward the bottom
|
---|
241 | of the playing area. This allows us to provide an implementation of
|
---|
242 | \l{QObject::}{timerEvent()} that we can use to update the widget.
|
---|
243 |
|
---|
244 | \section1 TetrixBoard Class Implementation
|
---|
245 |
|
---|
246 | In the constructor, we customize the frame style of the widget, ensure that
|
---|
247 | keyboard input will be received by the widget by using Qt::StrongFocus for the
|
---|
248 | focus policy, and initialize the game state:
|
---|
249 |
|
---|
250 | \snippet examples/widgets/tetrix/tetrixboard.cpp 0
|
---|
251 |
|
---|
252 | The first (next) piece is also set up with a random shape.
|
---|
253 |
|
---|
254 | The \c setNextPieceLabel() function is used to pass in an externally-constructed
|
---|
255 | label to the board, so that it can be shown alongside the playing area:
|
---|
256 |
|
---|
257 | \snippet examples/widgets/tetrix/tetrixboard.cpp 1
|
---|
258 |
|
---|
259 | We provide a reasonable size hint and minimum size hint for the board, based on
|
---|
260 | the size of the space for each block in the playing area:
|
---|
261 |
|
---|
262 | \snippet examples/widgets/tetrix/tetrixboard.cpp 2
|
---|
263 | \snippet examples/widgets/tetrix/tetrixboard.cpp 3
|
---|
264 |
|
---|
265 | By using a minimum size hint, we indicate to the layout in the parent widget
|
---|
266 | that the board should not shrink below a minimum size.
|
---|
267 |
|
---|
268 | A new game is started when the \c start() slot is called. This resets the
|
---|
269 | game's state, the player's score and level, and the contents of the board:
|
---|
270 |
|
---|
271 | \snippet examples/widgets/tetrix/tetrixboard.cpp 4
|
---|
272 |
|
---|
273 | We also emit signals to inform other components of these changes before creating
|
---|
274 | a new piece that is ready to be dropped into the playing area. We start the
|
---|
275 | timer that determines how often the piece drops down one row on the board.
|
---|
276 |
|
---|
277 | The \c pause() slot is used to temporarily stop the current game by stopping the
|
---|
278 | internal timer:
|
---|
279 |
|
---|
280 | \snippet examples/widgets/tetrix/tetrixboard.cpp 5
|
---|
281 | \snippet examples/widgets/tetrix/tetrixboard.cpp 6
|
---|
282 |
|
---|
283 | We perform checks to ensure that the game can only be paused if it is already
|
---|
284 | running and not already paused.
|
---|
285 |
|
---|
286 | The \c paintEvent() function is straightforward to implement. We begin by
|
---|
287 | calling the base class's implementation of \l{QWidget::}{paintEvent()} before
|
---|
288 | constructing a QPainter for use on the board:
|
---|
289 |
|
---|
290 | \snippet examples/widgets/tetrix/tetrixboard.cpp 7
|
---|
291 |
|
---|
292 | Since the board is a subclass of QFrame, we obtain a QRect that covers the area
|
---|
293 | \e inside the frame decoration before drawing our own content.
|
---|
294 |
|
---|
295 | If the game is paused, we want to hide the existing state of the board and
|
---|
296 | show some text. We achieve this by painting text onto the widget and returning
|
---|
297 | early from the function. The rest of the painting is performed after this point.
|
---|
298 |
|
---|
299 | The position of the top of the board is found by subtracting the total height
|
---|
300 | of each space on the board from the bottom of the frame's internal rectangle.
|
---|
301 | For each space on the board that is occupied by a piece, we call the
|
---|
302 | \c drawSquare() function to draw a block at that position.
|
---|
303 |
|
---|
304 | \snippet examples/widgets/tetrix/tetrixboard.cpp 8
|
---|
305 | \snippet examples/widgets/tetrix/tetrixboard.cpp 9
|
---|
306 |
|
---|
307 | Spaces that are not occupied by blocks are left blank.
|
---|
308 |
|
---|
309 | Unlike the existing pieces on the board, the current piece is drawn
|
---|
310 | block-by-block at its current position:
|
---|
311 |
|
---|
312 | \snippet examples/widgets/tetrix/tetrixboard.cpp 10
|
---|
313 | \snippet examples/widgets/tetrix/tetrixboard.cpp 11
|
---|
314 | \snippet examples/widgets/tetrix/tetrixboard.cpp 12
|
---|
315 |
|
---|
316 | The \c keyPressEvent() handler is called whenever the player presses a key while
|
---|
317 | the \c TetrixBoard widget has the keyboard focus.
|
---|
318 |
|
---|
319 | \snippet examples/widgets/tetrix/tetrixboard.cpp 13
|
---|
320 |
|
---|
321 | If there is no current game, the game is running but paused, or if there is no
|
---|
322 | current shape to control, we simply pass on the event to the base class.
|
---|
323 |
|
---|
324 | We check whether the event is about any of the keys that the player uses to
|
---|
325 | control the current piece and, if so, we call the relevant function to handle
|
---|
326 | the input:
|
---|
327 |
|
---|
328 | \snippet examples/widgets/tetrix/tetrixboard.cpp 14
|
---|
329 |
|
---|
330 | In the case where the player presses a key that we are not interested in, we
|
---|
331 | again pass on the event to the base class's implementation of
|
---|
332 | \l{QWidget::}{keyPressEvent()}.
|
---|
333 |
|
---|
334 | The \c timerEvent() handler is called every time the class's QBasicTimer
|
---|
335 | instance times out. We need to check that the event we receive corresponds to
|
---|
336 | our timer. If it does, we can update the board:
|
---|
337 |
|
---|
338 | \snippet examples/widgets/tetrix/tetrixboard.cpp 15
|
---|
339 | \snippet examples/widgets/tetrix/tetrixboard.cpp 16
|
---|
340 | \snippet examples/widgets/tetrix/tetrixboard.cpp 17
|
---|
341 |
|
---|
342 | If a row (or line) has just been filled, we create a new piece and reset the
|
---|
343 | timer; otherwise we move the current piece down by one row. We let the base
|
---|
344 | class handle other timer events that we receive.
|
---|
345 |
|
---|
346 | The \c clearBoard() function simply fills the board with the
|
---|
347 | \c TetrixShape::NoShape value:
|
---|
348 |
|
---|
349 | \snippet examples/widgets/tetrix/tetrixboard.cpp 18
|
---|
350 |
|
---|
351 | The \c dropDown() function moves the current piece down as far as possible on
|
---|
352 | the board, either until it is touching the bottom of the playing area or it is
|
---|
353 | stacked on top of another piece:
|
---|
354 |
|
---|
355 | \snippet examples/widgets/tetrix/tetrixboard.cpp 19
|
---|
356 | \snippet examples/widgets/tetrix/tetrixboard.cpp 20
|
---|
357 |
|
---|
358 | The number of rows the piece has dropped is recorded and passed to the
|
---|
359 | \c pieceDropped() function so that the player's score can be updated.
|
---|
360 |
|
---|
361 | The \c oneLineDown() function is used to move the current piece down by one row
|
---|
362 | (line), either when the user presses the \gui{D} key or when the piece is
|
---|
363 | scheduled to move:
|
---|
364 |
|
---|
365 | \snippet examples/widgets/tetrix/tetrixboard.cpp 21
|
---|
366 |
|
---|
367 | If the piece cannot drop down by one line, we call the \c pieceDropped() function
|
---|
368 | with zero as the argument to indicate that it cannot fall any further, and that
|
---|
369 | the player should receive no extra points for the fall.
|
---|
370 |
|
---|
371 | The \c pieceDropped() function itself is responsible for awarding points to the
|
---|
372 | player for positioning the current piece, checking for full rows on the board
|
---|
373 | and, if no lines have been removed, creating a new piece to replace the current
|
---|
374 | one:
|
---|
375 |
|
---|
376 | \snippet examples/widgets/tetrix/tetrixboard.cpp 22
|
---|
377 | \snippet examples/widgets/tetrix/tetrixboard.cpp 23
|
---|
378 |
|
---|
379 | We call \c removeFullLines() each time a piece has been dropped. This scans
|
---|
380 | the board from bottom to top, looking for blank spaces on each row.
|
---|
381 |
|
---|
382 | \snippet examples/widgets/tetrix/tetrixboard.cpp 24
|
---|
383 | \snippet examples/widgets/tetrix/tetrixboard.cpp 25
|
---|
384 | \snippet examples/widgets/tetrix/tetrixboard.cpp 26
|
---|
385 | \snippet examples/widgets/tetrix/tetrixboard.cpp 27
|
---|
386 |
|
---|
387 | If a row contains no blank spaces, the rows above it are copied down by one row
|
---|
388 | to compress the stack of pieces, the top row on the board is cleared, and the
|
---|
389 | number of full lines found is incremented.
|
---|
390 |
|
---|
391 | \snippet examples/widgets/tetrix/tetrixboard.cpp 28
|
---|
392 | \snippet examples/widgets/tetrix/tetrixboard.cpp 29
|
---|
393 |
|
---|
394 | If some lines have been removed, the player's score and the total number of lines
|
---|
395 | removed are updated. The \c linesRemoved() and \c scoreChanged() signals are
|
---|
396 | emitted to send these new values to other widgets in the window.
|
---|
397 |
|
---|
398 | Additionally, we set the timer to elapse after half a second, set the
|
---|
399 | \c isWaitingAfterLine flag to indicate that lines have been removed, unset
|
---|
400 | the piece's shape to ensure that it is not drawn, and update the widget.
|
---|
401 | The next time that the \c timerEvent() handler is called, a new piece will be
|
---|
402 | created and the game will continue.
|
---|
403 |
|
---|
404 | The \c newPiece() function places the next available piece at the top of the
|
---|
405 | board, and creates a new piece with a random shape:
|
---|
406 |
|
---|
407 | \snippet examples/widgets/tetrix/tetrixboard.cpp 30
|
---|
408 | \snippet examples/widgets/tetrix/tetrixboard.cpp 31
|
---|
409 |
|
---|
410 | We place a new piece in the middle of the board at the top. The game is over if
|
---|
411 | the piece can't move, so we unset its shape to prevent it from being drawn, stop
|
---|
412 | the timer, and unset the \c isStarted flag.
|
---|
413 |
|
---|
414 | The \c showNextPiece() function updates the label that shows the next piece to
|
---|
415 | be dropped:
|
---|
416 |
|
---|
417 | \snippet examples/widgets/tetrix/tetrixboard.cpp 32
|
---|
418 | \snippet examples/widgets/tetrix/tetrixboard.cpp 33
|
---|
419 |
|
---|
420 | We draw the piece's component blocks onto a pixmap that is then set on the label.
|
---|
421 |
|
---|
422 | The \c tryMove() function is used to determine whether a piece can be positioned
|
---|
423 | at the specified coordinates:
|
---|
424 |
|
---|
425 | \snippet examples/widgets/tetrix/tetrixboard.cpp 34
|
---|
426 |
|
---|
427 | We examine the spaces on the board that the piece needs to occupy and, if they
|
---|
428 | are already occupied by other pieces, we return \c false to indicate that the
|
---|
429 | move has failed.
|
---|
430 |
|
---|
431 | \snippet examples/widgets/tetrix/tetrixboard.cpp 35
|
---|
432 |
|
---|
433 | If the piece could be placed on the board at the desired location, we update the
|
---|
434 | current piece and its position, update the widget, and return \c true to indicate
|
---|
435 | success.
|
---|
436 |
|
---|
437 | The \c drawSquare() function draws the blocks (normally squares) that make up
|
---|
438 | each piece using different colors for pieces with different shapes:
|
---|
439 |
|
---|
440 | \snippet examples/widgets/tetrix/tetrixboard.cpp 36
|
---|
441 |
|
---|
442 | We obtain the color to use from a look-up table that relates each shape to an
|
---|
443 | RGB value, and use the painter provided to draw the block at the specified
|
---|
444 | coordinates.
|
---|
445 | */
|
---|