Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

gtetrix.cpp

Go to the documentation of this file.
00001 /**********************************************************************
00002 ** Copyright (C) 2000 Trolltech AS.  All rights reserved.
00003 **
00004 ** This file is part of Qtopia Environment.
00005 **
00006 ** This file may be distributed and/or modified under the terms of the
00007 ** GNU General Public License version 2 as published by the Free Software
00008 ** Foundation and appearing in the file LICENSE.GPL included in the
00009 ** packaging of this file.
00010 **
00011 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00012 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00013 **
00014 ** See http://www.trolltech.com/gpl/ for GPL licensing information.
00015 **
00016 ** Contact info@trolltech.com if any conditions of this licensing are
00017 ** not clear to you.
00018 **
00019 **********************************************************************/
00020 
00021 
00022 #include "gtetrix.h"
00023 
00024 #include <string.h>
00025 
00026 GenericTetrix::GenericTetrix(int boardWidth,int boardHeight)
00027 {
00028     int i,j;
00029 
00030     width    = boardWidth;
00031     height   = boardHeight;
00032     boardPtr = new int[height*width]; // Note the order, this makes it easier
00033                                       // to remove full lines.
00034     for(i = 0 ; i < height ; i++)
00035         for(j = 0 ; j < width ; j++)
00036             board(j,i) = 0;
00037     currentLine       = -1;           // -1 if no falling piece.
00038     currentPos        = 0;
00039     showNext          = 0;            // FALSE
00040     nLinesRemoved     = 0;
00041     nPiecesDropped    = 0;
00042     score             = 0;
00043     level             = 1;
00044     gameID            = 0;
00045     nClearLines       = height;
00046 }
00047 
00048 GenericTetrix::~GenericTetrix()
00049 {
00050     delete[] boardPtr;
00051 }
00052 
00053 
00054 void GenericTetrix::clearBoard(int fillRandomLines)
00055 {
00056     int i,j;
00057 
00058     if (fillRandomLines >= height)
00059         fillRandomLines = height - 1;
00060 
00061     erasePiece();
00062     for(i = height - nClearLines - 1 ; i >= fillRandomLines ; i--)
00063         for(j = 0 ; j < width ; j++)
00064             if (board(j,i) != 0) {
00065                 draw(j,i,0);
00066                 board(j,i) = 0;
00067             }
00068     if (fillRandomLines != 0)
00069         for (i = 0 ; i < fillRandomLines ; i++) {
00070             fillRandom(i);
00071     }
00072     nClearLines = height - fillRandomLines;
00073 }
00074 
00075 void GenericTetrix::showBoard()
00076 {
00077     int i,j;
00078 
00079     showPiece();
00080     for(i = height - nClearLines - 1 ; i >= 0 ; i--)
00081         for(j = 0 ; j < width ; j++)
00082             if (board(j,i) != 0)
00083                 draw(j,i,board(j,i));
00084 }
00085 
00086 void GenericTetrix::hideBoard()
00087 {
00088     int i,j;
00089 
00090     erasePiece();
00091     for(i = height - nClearLines - 1 ; i >= 0 ; i--)
00092         for(j = 0 ; j < width ; j++)
00093             if (board(j,i) != 0)
00094                 draw(j,i,0);
00095 }
00096 
00097 void GenericTetrix::startGame(int gameType,int fillRandomLines)
00098 {
00099     gameID             = gameType;
00100     clearBoard(fillRandomLines);
00101     nLinesRemoved      = 0;
00102     updateRemoved(nLinesRemoved);
00103     nClearLines        = height;
00104     nPiecesDropped     = 0;
00105     score              = 0;
00106     updateScore(score);
00107     level              = 1;
00108     updateLevel(level);
00109     newPiece();
00110 }
00111 
00112 void GenericTetrix::revealNextPiece(int revealIt)
00113 {
00114     if (showNext == revealIt)
00115         return;
00116     showNext = revealIt;
00117     if (!showNext)
00118         eraseNextPiece();
00119     else
00120         showNextPiece();
00121 }
00122 
00123 void GenericTetrix::updateBoard(int x1,int y1,int x2, int y2,
00124                                 int dontUpdateBlanks)
00125 {
00126     int i,j;
00127     int tmp;
00128 
00129     if (x1 > x2) {
00130         tmp = x2;
00131         x2  = x1;
00132         x1  = tmp;
00133     }
00134     if (y1 > y2) {
00135         tmp = y2;
00136         y2  = y1;
00137         y1  = tmp;
00138     }
00139     if (x1 < 0)
00140         x1 = 0;
00141     if (x2 >= width)
00142         x2 = width - 1;
00143     if (y1 < 0)
00144         y1 = 0;
00145     if (y2 >= height)
00146         y2 = height - 1;
00147     for(i = y1 ; i <= y2 ; i++)
00148         for(j = x1 ; j <=  x2 ; j++)
00149             if (!dontUpdateBlanks || board(j,height - i - 1) != 0)
00150                 draw(j,height - i - 1,board(j,height - i - 1));
00151     showPiece();        // Remember to update piece correctly!!!!
00152 }
00153 
00154 
00155 void GenericTetrix::fillRandom(int line)
00156 {
00157     int i,j;
00158     int holes;
00159 
00160     for(i = 0 ; i < width ; i++)
00161         board(i,line) = TetrixPiece::randomValue(7);
00162     holes = 0;
00163     for(i = 0 ; i < width ; i++)
00164         if (board(i,line) == 0)   // Count holes in the line.
00165             holes++;
00166     if (holes == 0)                // Full line, make a random hole:
00167         board(TetrixPiece::randomValue(width),line) = 0;
00168     if (holes == width)            // Empty line, make a random square:
00169         board(TetrixPiece::randomValue(width),line) = 
00170                                     TetrixPiece::randomValue(6) + 1;
00171     for(j = 0 ; j < width ; j++)
00172         draw(j,i,board(j,i));
00173 }
00174 
00175 void GenericTetrix::moveLeft(int steps)
00176 {
00177     while(steps) {
00178         if (!canMoveTo(currentPos - 1,currentLine))
00179             return;
00180         moveTo(currentPos - 1,currentLine);
00181         steps--;
00182     }
00183 }
00184 
00185 void GenericTetrix::moveRight(int steps)
00186 {
00187     while(steps) {
00188         if (!canMoveTo(currentPos + 1,currentLine))
00189             return;
00190         moveTo(currentPos + 1,currentLine);
00191         steps--;
00192     }
00193 }
00194 
00195 void GenericTetrix::rotateLeft()
00196 {
00197     TetrixPiece tmp(currentPiece);
00198 
00199     tmp.rotateLeft();
00200     if (!canPosition(tmp))
00201         return;
00202     position(tmp);
00203     currentPiece = tmp;
00204 }
00205 
00206 void GenericTetrix::rotateRight()
00207 {
00208     TetrixPiece tmp(currentPiece);
00209 
00210     tmp.rotateRight();
00211     if (!canPosition(tmp))
00212         return;
00213     position(tmp);
00214     currentPiece = tmp;
00215 }
00216 
00217 void GenericTetrix::dropDown()
00218 {
00219     if (currentLine == -1)
00220         return;
00221 
00222     int dropHeight = 0;
00223     int newLine    = currentLine;
00224     while(newLine) {
00225         if (!canMoveTo(currentPos,newLine - 1))
00226             break;
00227         newLine--;
00228         dropHeight++;
00229     }
00230     if (dropHeight != 0)
00231         moveTo(currentPos,newLine);
00232     internalPieceDropped(dropHeight);
00233 }
00234 
00235 void GenericTetrix::oneLineDown()
00236 {
00237     if (currentLine == -1)
00238         return;
00239     if (canMoveTo(currentPos,currentLine - 1)) {
00240         moveTo(currentPos,currentLine - 1);
00241     } else {
00242         internalPieceDropped(0);
00243     }
00244 }
00245 
00246 void GenericTetrix::newPiece()
00247 {
00248     currentPiece = nextPiece;
00249     if (showNext)
00250         eraseNextPiece();
00251     nextPiece.setRandomType();
00252     if (showNext)
00253         showNextPiece();
00254     currentLine = height - 1 + currentPiece.getMinY();
00255     currentPos  = width/2 + 1;
00256     if (!canMoveTo(currentPos,currentLine)) {
00257         currentLine = -1;
00258         gameOver();
00259     } else {
00260         showPiece();
00261     }
00262 }
00263 
00264 void GenericTetrix::removePiece()
00265 {
00266     erasePiece();
00267     currentLine = -1;
00268 }
00269 
00270 void GenericTetrix::drawNextSquare(int,int,int)
00271 {
00272 
00273 }
00274 
00275 void GenericTetrix::pieceDropped(int)
00276 {
00277     newPiece();
00278 }
00279 
00280 void GenericTetrix::updateRemoved(int) 
00281 {
00282 }
00283 
00284 void GenericTetrix::updateScore(int)
00285 {
00286 }
00287 
00288 void GenericTetrix::updateLevel(int)
00289 {
00290 }
00291 
00292 void GenericTetrix::removeFullLines()
00293 {
00294     int i,j,k;
00295     int nFullLines;
00296     
00297     for(i = 0 ; i < height - nClearLines ; i++) {
00298         for(j = 0 ; j < width ; j++)
00299             if (board(j,i) == 0)
00300                 break;
00301         if (j == width) {
00302             nFullLines = 1;
00303             for(k = i + 1 ; k < height - nClearLines ; k++) {
00304                 for(j = 0 ; j < width ; j++)
00305                     if (board(j,k) == 0)
00306                         break;
00307                 if (j == width) {
00308                     nFullLines++;
00309                 } else {
00310                     for(j = 0 ; j < width ; j++) {                      
00311                         if (board(j,k - nFullLines) != board(j,k)) {
00312                             board(j,k - nFullLines) = board(j,k);
00313                             draw(      j,k - nFullLines,
00314                                        board(j,k - nFullLines));
00315                         }
00316                     }
00317                 }
00318             }
00319             nClearLines   = nClearLines + nFullLines;
00320             nLinesRemoved = nLinesRemoved + nFullLines;
00321             updateRemoved(nLinesRemoved);
00322             score = score + 10*nFullLines; // updateScore must be
00323                                            // called by caller!
00324             for (i = height - nClearLines              ;
00325                  i < height - nClearLines + nFullLines ;
00326                  i++)
00327                 for(j = 0 ; j < width ; j++)
00328                     if (board(j,i) != 0) {
00329                         draw(j,i,0);
00330                         board(j,i) = 0;
00331                     }
00332         }
00333     }
00334 }
00335 
00336 void GenericTetrix::showPiece()
00337 {
00338     int x,y;
00339 
00340     if (currentLine == -1)
00341         return;
00342 
00343     for(int i = 0 ; i < 4 ; i++) {
00344         currentPiece.getCoord(i,x,y);
00345         draw(currentPos + x,currentLine - y,currentPiece.getType());
00346     }
00347 }
00348 
00349 void GenericTetrix::erasePiece()
00350 {
00351     int x,y;
00352 
00353     if (currentLine == -1)
00354         return;
00355 
00356     for(int i = 0 ; i < 4 ; i++) {
00357         currentPiece.getCoord(i,x,y);
00358         draw(currentPos + x,currentLine - y,0);
00359     }
00360 }
00361 
00362 void GenericTetrix::internalPieceDropped(int dropHeight)
00363 {
00364     gluePiece();
00365     nPiecesDropped++;
00366     if (nPiecesDropped % 25 == 0) {
00367         level++;
00368         updateLevel(level);
00369     }
00370     score = score + 7 + dropHeight;
00371     removeFullLines();
00372     updateScore(score);
00373     pieceDropped(dropHeight);
00374 }
00375 
00376 void GenericTetrix::gluePiece()
00377 {
00378     int x,y;
00379     int min;
00380 
00381     if (currentLine == -1)
00382         return;
00383     
00384     for(int i = 0 ; i < 4 ; i++) {
00385         currentPiece.getCoord(i,x,y);
00386         board(currentPos + x,currentLine - y) = currentPiece.getType();
00387     }
00388     min = currentPiece.getMinY();
00389     if (currentLine - min >= height - nClearLines)
00390         nClearLines = height - currentLine + min - 1;
00391 }
00392 
00393 void GenericTetrix::showNextPiece(int erase)
00394 {
00395     int x,y;
00396     int minX = nextPiece.getMinX();
00397     int minY = nextPiece.getMinY();
00398     int maxX = nextPiece.getMaxX();
00399     int maxY = nextPiece.getMaxY();
00400 
00401     int xOffset = (3 - (maxX - minX))/2;
00402     int yOffset = (3 - (maxY - minY))/2;
00403 
00404     for(int i = 0 ; i < 4 ; i++) {
00405         nextPiece.getCoord(i,x,y);
00406         if (erase)
00407             drawNextSquare(x + xOffset - minX,
00408                            y + yOffset - minY,0);
00409         else
00410             drawNextSquare(x + xOffset - minX,
00411                            y + yOffset - minY,nextPiece.getType());
00412     }
00413 }
00414 
00415 int GenericTetrix::canPosition(TetrixPiece &piece)
00416 {
00417     if (currentLine == -1)
00418         return 0;
00419 
00420     int x,y;
00421 
00422     for(int i = 0 ; i < 4 ; i++) {
00423         piece.getCoord(i,x,y);
00424         x = currentPos + x;
00425         y = currentLine - y; // Board and pieces have inverted y-coord. systems.
00426         if (x < 0 || x >= width || y < 0 || y >= height)
00427             return 0;     // Outside board, cannot put piece here.
00428         if (board(x,y) != 0)
00429             return 0;     // Over a non-zero square, cannot put piece here.
00430     }
00431     return 1;             // Inside board and no non-zero squares underneath.
00432 
00433 }
00434 
00435 int GenericTetrix::canMoveTo(int xPosition,int line)
00436 {
00437     if (currentLine == -1)
00438         return 0;
00439 
00440     int x,y;
00441 
00442     for(int i = 0 ; i < 4 ; i++) {
00443         currentPiece.getCoord(i,x,y);
00444         x = xPosition + x;
00445         y = line - y;     // Board and pieces have inverted y-coord. systems.
00446         if (x < 0 || x >= width || y < 0 || y >= height)
00447             return 0;     // Outside board, cannot put piece here.
00448         if (board(x,y) != 0)
00449             return 0;     // Over a non-zero square, cannot put piece here.
00450     }
00451     return 1;             // Inside board and no non-zero squares underneath.
00452 }
00453 
00454 void GenericTetrix::moveTo(int xPosition,int line)
00455 {
00456     if (currentLine == -1)
00457         return;
00458     optimizedMove(xPosition,line,currentPiece);
00459     currentPos  = xPosition;
00460     currentLine = line;
00461 }
00462 
00463 void GenericTetrix::position(TetrixPiece &piece)
00464 {
00465     if (currentLine == -1)
00466         return;
00467 
00468     optimizedMove(currentPos,currentLine,piece);
00469 }
00470 
00471 void GenericTetrix::optimizedMove(int newPos, int newLine,
00472                                   TetrixPiece &newPiece)
00473 {
00474     int updates [8][3];
00475     int nUpdates;
00476     int value;
00477     int x,y;
00478     int i,j;
00479 
00480     for(i = 0 ; i < 4 ; i++) { // Put the erasing coords into updates
00481         currentPiece.getCoord(i,x,y);
00482         updates[i][0] = currentPos  + x;
00483         updates[i][1] = currentLine - y;
00484         updates[i][2] = 0;
00485     }
00486     nUpdates = 4;
00487     for(i = 0 ; i < 4 ; i++) { // Any drawing coord same as an erasing one?
00488         newPiece.getCoord(i,x,y);
00489         x = newPos  + x;
00490         y = newLine - y;
00491         for (j = 0 ; j < 4 ; j++)
00492             if (updates[j][0] == x && updates[j][1] == y) { // Same coord,
00493                                                         // don't have to erase
00494                 if (currentPiece.getType() == newPiece.getType())
00495                     updates[j][2] = -1; // Correct on screen, no update!
00496                 else
00497                     updates[j][2] = newPiece.getType();
00498                 break;
00499             }
00500         if (j == 4) {         // This coord does not overlap an erasing one
00501             updates[nUpdates][0] = x;
00502             updates[nUpdates][1] = y;
00503             updates[nUpdates][2] = newPiece.getType();
00504             nUpdates++;
00505         }
00506     }
00507     for (i = 0 ; i < nUpdates ; i++) {  // Do the updating
00508         x     = updates[i][0];
00509         y     = updates[i][1];
00510         value = updates[i][2];
00511         if (value != -1)                // Only update if new value != current
00512             draw(x,y,value);
00513     }
00514 }

Generated on Sat Nov 5 16:17:27 2005 for OPIE by  doxygen 1.4.2