source: trunk/examples/tetrix/gtetrix.cpp

Last change on this file was 160, checked in by dmik, 19 years ago

Imported table and iconview modules and a bunch of dependent examples from the official release 3.3.1 from Trolltech.

  • Property svn:keywords set to Id
File size: 12.3 KB
Line 
1/****************************************************************************
2** $Id: gtetrix.cpp 160 2006-12-11 20:15:57Z dmik $
3**
4** Copyright (C) 1992-2000 Trolltech AS. All rights reserved.
5**
6** This file is part of an example program for Qt. This example
7** program may be used, distributed and modified without limitation.
8**
9*****************************************************************************/
10
11#include "gtetrix.h"
12
13#include <string.h>
14
15GenericTetrix::GenericTetrix(int boardWidth,int boardHeight)
16{
17 int i,j;
18
19 width = boardWidth;
20 height = boardHeight;
21 boardPtr = new int[height*width]; // Note the order, this makes it easier
22 // to remove full lines.
23 for(i = 0 ; i < height ; i++)
24 for(j = 0 ; j < width ; j++)
25 board(j,i) = 0;
26 currentLine = -1; // -1 if no falling piece.
27 currentPos = 0;
28 showNext = 0; // FALSE
29 nLinesRemoved = 0;
30 nPiecesDropped = 0;
31 score = 0;
32 level = 1;
33 gameID = 0;
34 nClearLines = height;
35}
36
37GenericTetrix::~GenericTetrix()
38{
39 delete[] boardPtr;
40}
41
42
43void GenericTetrix::clearBoard(int fillRandomLines)
44{
45 int i,j;
46
47 if (fillRandomLines >= height)
48 fillRandomLines = height - 1;
49
50 erasePiece();
51 for(i = height - nClearLines - 1 ; i >= fillRandomLines ; i--)
52 for(j = 0 ; j < width ; j++)
53 if (board(j,i) != 0) {
54 draw(j,i,0);
55 board(j,i) = 0;
56 }
57 if (fillRandomLines != 0)
58 for (i = 0 ; i < fillRandomLines ; i++) {
59 fillRandom(i);
60 }
61 nClearLines = height - fillRandomLines;
62}
63
64void GenericTetrix::showBoard()
65{
66 int i,j;
67
68 showPiece();
69 for(i = height - nClearLines - 1 ; i >= 0 ; i--)
70 for(j = 0 ; j < width ; j++)
71 if (board(j,i) != 0)
72 draw(j,i,board(j,i));
73}
74
75void GenericTetrix::hideBoard()
76{
77 int i,j;
78
79 erasePiece();
80 for(i = height - nClearLines - 1 ; i >= 0 ; i--)
81 for(j = 0 ; j < width ; j++)
82 if (board(j,i) != 0)
83 draw(j,i,0);
84}
85
86void GenericTetrix::startGame(int gameType,int fillRandomLines)
87{
88 gameID = gameType;
89 clearBoard(fillRandomLines);
90 nLinesRemoved = 0;
91 updateRemoved(nLinesRemoved);
92 nClearLines = height;
93 nPiecesDropped = 0;
94 score = 0;
95 updateScore(score);
96 level = 1;
97 updateLevel(level);
98 newPiece();
99}
100
101void GenericTetrix::revealNextPiece(int revealIt)
102{
103 if (showNext == revealIt)
104 return;
105 showNext = revealIt;
106 if (!showNext)
107 eraseNextPiece();
108 else
109 showNextPiece();
110}
111
112void GenericTetrix::updateBoard(int x1,int y1,int x2, int y2,
113 int dontUpdateBlanks)
114{
115 int i,j;
116 int tmp;
117
118 if (x1 > x2) {
119 tmp = x2;
120 x2 = x1;
121 x1 = tmp;
122 }
123 if (y1 > y2) {
124 tmp = y2;
125 y2 = y1;
126 y1 = tmp;
127 }
128 if (x1 < 0)
129 x1 = 0;
130 if (x2 >= width)
131 x2 = width - 1;
132 if (y1 < 0)
133 y1 = 0;
134 if (y2 >= height)
135 y2 = height - 1;
136 for(i = y1 ; i <= y2 ; i++)
137 for(j = x1 ; j <= x2 ; j++)
138 if (!dontUpdateBlanks || board(j,height - i - 1) != 0)
139 draw(j,height - i - 1,board(j,height - i - 1));
140 showPiece(); // Remember to update piece correctly!!!!
141}
142
143
144void GenericTetrix::fillRandom(int line)
145{
146 int i,j;
147 int holes;
148
149 for(i = 0 ; i < width ; i++)
150 board(i,line) = TetrixPiece::randomValue(7);
151 holes = 0;
152 for(i = 0 ; i < width ; i++)
153 if (board(i,line) == 0) // Count holes in the line.
154 holes++;
155 if (holes == 0) // Full line, make a random hole:
156 board(TetrixPiece::randomValue(width),line) = 0;
157 if (holes == width) // Empty line, make a random square:
158 board(TetrixPiece::randomValue(width),line) =
159 TetrixPiece::randomValue(6) + 1;
160 for(j = 0 ; j < width ; j++)
161 draw(j,i,board(j,i));
162}
163
164void GenericTetrix::moveLeft(int steps)
165{
166 while(steps) {
167 if (!canMoveTo(currentPos - 1,currentLine))
168 return;
169 moveTo(currentPos - 1,currentLine);
170 steps--;
171 }
172}
173
174void GenericTetrix::moveRight(int steps)
175{
176 while(steps) {
177 if (!canMoveTo(currentPos + 1,currentLine))
178 return;
179 moveTo(currentPos + 1,currentLine);
180 steps--;
181 }
182}
183
184void GenericTetrix::rotateLeft()
185{
186 TetrixPiece tmp(currentPiece);
187
188 tmp.rotateLeft();
189 if (!canPosition(tmp))
190 return;
191 position(tmp);
192 currentPiece = tmp;
193}
194
195void GenericTetrix::rotateRight()
196{
197 TetrixPiece tmp(currentPiece);
198
199 tmp.rotateRight();
200 if (!canPosition(tmp))
201 return;
202 position(tmp);
203 currentPiece = tmp;
204}
205
206void GenericTetrix::dropDown()
207{
208 if (currentLine == -1)
209 return;
210
211 int dropHeight = 0;
212 int newLine = currentLine;
213 while(newLine) {
214 if (!canMoveTo(currentPos,newLine - 1))
215 break;
216 newLine--;
217 dropHeight++;
218 }
219 if (dropHeight != 0)
220 moveTo(currentPos,newLine);
221 internalPieceDropped(dropHeight);
222}
223
224void GenericTetrix::oneLineDown()
225{
226 if (currentLine == -1)
227 return;
228 if (canMoveTo(currentPos,currentLine - 1)) {
229 moveTo(currentPos,currentLine - 1);
230 } else {
231 internalPieceDropped(0);
232 }
233}
234
235void GenericTetrix::newPiece()
236{
237 currentPiece = nextPiece;
238 if (showNext)
239 eraseNextPiece();
240 nextPiece.setRandomType();
241 if (showNext)
242 showNextPiece();
243 currentLine = height - 1 + currentPiece.getMinY();
244 currentPos = width/2 + 1;
245 if (!canMoveTo(currentPos,currentLine)) {
246 currentLine = -1;
247 gameOver();
248 } else {
249 showPiece();
250 }
251}
252
253void GenericTetrix::removePiece()
254{
255 erasePiece();
256 currentLine = -1;
257}
258
259void GenericTetrix::drawNextSquare(int,int,int)
260{
261
262}
263
264void GenericTetrix::pieceDropped(int)
265{
266 newPiece();
267}
268
269void GenericTetrix::updateRemoved(int)
270{
271}
272
273void GenericTetrix::updateScore(int)
274{
275}
276
277void GenericTetrix::updateLevel(int)
278{
279}
280
281void GenericTetrix::removeFullLines()
282{
283 int i,j,k;
284 int nFullLines;
285
286 for(i = 0 ; i < height - nClearLines ; i++) {
287 for(j = 0 ; j < width ; j++)
288 if (board(j,i) == 0)
289 break;
290 if (j == width) {
291 nFullLines = 1;
292 for(k = i + 1 ; k < height - nClearLines ; k++) {
293 for(j = 0 ; j < width ; j++)
294 if (board(j,k) == 0)
295 break;
296 if (j == width) {
297 nFullLines++;
298 } else {
299 for(j = 0 ; j < width ; j++) {
300 if (board(j,k - nFullLines) != board(j,k)) {
301 board(j,k - nFullLines) = board(j,k);
302 draw( j,k - nFullLines,
303 board(j,k - nFullLines));
304 }
305 }
306 }
307 }
308 nClearLines = nClearLines + nFullLines;
309 nLinesRemoved = nLinesRemoved + nFullLines;
310 updateRemoved(nLinesRemoved);
311 score = score + 10*nFullLines; // updateScore must be
312 // called by caller!
313 for (i = height - nClearLines ;
314 i < height - nClearLines + nFullLines ;
315 i++)
316 for(j = 0 ; j < width ; j++)
317 if (board(j,i) != 0) {
318 draw(j,i,0);
319 board(j,i) = 0;
320 }
321 }
322 }
323}
324
325void GenericTetrix::showPiece()
326{
327 int x,y;
328
329 if (currentLine == -1)
330 return;
331
332 for(int i = 0 ; i < 4 ; i++) {
333 currentPiece.getCoord(i,x,y);
334 draw(currentPos + x,currentLine - y,currentPiece.getType());
335 }
336}
337
338void GenericTetrix::erasePiece()
339{
340 int x,y;
341
342 if (currentLine == -1)
343 return;
344
345 for(int i = 0 ; i < 4 ; i++) {
346 currentPiece.getCoord(i,x,y);
347 draw(currentPos + x,currentLine - y,0);
348 }
349}
350
351void GenericTetrix::internalPieceDropped(int dropHeight)
352{
353 gluePiece();
354 nPiecesDropped++;
355 if (nPiecesDropped % 25 == 0) {
356 level++;
357 updateLevel(level);
358 }
359 score = score + 7 + dropHeight;
360 removeFullLines();
361 updateScore(score);
362 pieceDropped(dropHeight);
363}
364
365void GenericTetrix::gluePiece()
366{
367 int x,y;
368 int min;
369
370 if (currentLine == -1)
371 return;
372
373 for(int i = 0 ; i < 4 ; i++) {
374 currentPiece.getCoord(i,x,y);
375 board(currentPos + x,currentLine - y) = currentPiece.getType();
376 }
377 min = currentPiece.getMinY();
378 if (currentLine - min >= height - nClearLines)
379 nClearLines = height - currentLine + min - 1;
380}
381
382void GenericTetrix::showNextPiece(int erase)
383{
384 int x,y;
385 int minX = nextPiece.getMinX();
386 int minY = nextPiece.getMinY();
387 int maxX = nextPiece.getMaxX();
388 int maxY = nextPiece.getMaxY();
389
390 int xOffset = (3 - (maxX - minX))/2;
391 int yOffset = (3 - (maxY - minY))/2;
392
393 for(int i = 0 ; i < 4 ; i++) {
394 nextPiece.getCoord(i,x,y);
395 if (erase)
396 drawNextSquare(x + xOffset - minX,
397 y + yOffset - minY,0);
398 else
399 drawNextSquare(x + xOffset - minX,
400 y + yOffset - minY,nextPiece.getType());
401 }
402}
403
404int GenericTetrix::canPosition(TetrixPiece &piece)
405{
406 if (currentLine == -1)
407 return 0;
408
409 int x,y;
410
411 for(int i = 0 ; i < 4 ; i++) {
412 piece.getCoord(i,x,y);
413 x = currentPos + x;
414 y = currentLine - y; // Board and pieces have inverted y-coord. systems.
415 if (x < 0 || x >= width || y < 0 || y >= height)
416 return 0; // Outside board, cannot put piece here.
417 if (board(x,y) != 0)
418 return 0; // Over a non-zero square, cannot put piece here.
419 }
420 return 1; // Inside board and no non-zero squares underneath.
421
422}
423
424int GenericTetrix::canMoveTo(int xPosition,int line)
425{
426 if (currentLine == -1)
427 return 0;
428
429 int x,y;
430
431 for(int i = 0 ; i < 4 ; i++) {
432 currentPiece.getCoord(i,x,y);
433 x = xPosition + x;
434 y = line - y; // Board and pieces have inverted y-coord. systems.
435 if (x < 0 || x >= width || y < 0 || y >= height)
436 return 0; // Outside board, cannot put piece here.
437 if (board(x,y) != 0)
438 return 0; // Over a non-zero square, cannot put piece here.
439 }
440 return 1; // Inside board and no non-zero squares underneath.
441}
442
443void GenericTetrix::moveTo(int xPosition,int line)
444{
445 if (currentLine == -1)
446 return;
447 optimizedMove(xPosition,line,currentPiece);
448 currentPos = xPosition;
449 currentLine = line;
450}
451
452void GenericTetrix::position(TetrixPiece &piece)
453{
454 if (currentLine == -1)
455 return;
456
457 optimizedMove(currentPos,currentLine,piece);
458}
459
460void GenericTetrix::optimizedMove(int newPos, int newLine,
461 TetrixPiece &newPiece)
462{
463 int updates [8][3];
464 int nUpdates;
465 int value;
466 int x,y;
467 int i,j;
468
469 for(i = 0 ; i < 4 ; i++) { // Put the erasing coords into updates
470 currentPiece.getCoord(i,x,y);
471 updates[i][0] = currentPos + x;
472 updates[i][1] = currentLine - y;
473 updates[i][2] = 0;
474 }
475 nUpdates = 4;
476 for(i = 0 ; i < 4 ; i++) { // Any drawing coord same as an erasing one?
477 newPiece.getCoord(i,x,y);
478 x = newPos + x;
479 y = newLine - y;
480 for (j = 0 ; j < 4 ; j++)
481 if (updates[j][0] == x && updates[j][1] == y) { // Same coord,
482 // don't have to erase
483 if (currentPiece.getType() == newPiece.getType())
484 updates[j][2] = -1; // Correct on screen, no update!
485 else
486 updates[j][2] = newPiece.getType();
487 break;
488 }
489 if (j == 4) { // This coord does not overlap an erasing one
490 updates[nUpdates][0] = x;
491 updates[nUpdates][1] = y;
492 updates[nUpdates][2] = newPiece.getType();
493 nUpdates++;
494 }
495 }
496 for (i = 0 ; i < nUpdates ; i++) { // Do the updating
497 x = updates[i][0];
498 y = updates[i][1];
499 value = updates[i][2];
500 if (value != -1) // Only update if new value != current
501 draw(x,y,value);
502 }
503}
Note: See TracBrowser for help on using the repository browser.