Tetris.cxx

Go to the documentation of this file.
00001 // @(#)root/test:$Id: Tetris.cxx 36320 2010-10-12 19:00:12Z brun $
00002 // Author: Valeriy Onuchin & Fons Rademakers   04/10/98
00003 
00004 ///////////////////////////////////////////////////////////////////
00005 //  ROOT implementation of the simple Tetris game
00006 //  Layout and some hints were taken from Qt /examples/tetris
00007 //
00008 //  To run this game do the following:
00009 //  $ root
00010 //  root [0] gSystem.Load("libGpad")
00011 //  root [1] gSystem.Load("Tetris")
00012 //  root [2] Tetris t
00013 //  <play game>
00014 //  root [2] .q
00015 //
00016 ///////////////////////////////////////////////////////////////////
00017 
00018 #include <TVirtualX.h>
00019 #include <TGClient.h>
00020 #include <KeySymbols.h>
00021 #include <TRootCanvas.h>
00022 #include <TApplication.h>
00023 #include <TList.h>
00024 #include "Tetris.h"
00025 
00026 static Tetris *gTetris;                    // game manager
00027 
00028 static const UInt_t gBoxPixelSize = 20;   // size of TetrisBox in pixels
00029 
00030 
00031 ClassImp(Tetris)
00032 
00033 ///////////////////////////////////////////////////////////////////
00034 //  TetrisBox - the main brick of the game
00035 ///////////////////////////////////////////////////////////////////
00036 TetrisBox::TetrisBox(Int_t x, Int_t y, UInt_t type, TPad* pad) :
00037    TWbox(0,0,1,1,33,2,1)
00038 {
00039    // Create brick
00040 
00041    fType = type;
00042    fPad  = pad;
00043 
00044    //-------  append box to pad
00045    SetBit(kMustCleanup);
00046    SetBit(kCanDelete);
00047    pad->GetListOfPrimitives()->Add(this);
00048    SetXY(x,y);
00049 }
00050 
00051 void TetrisBox::SetX(Int_t x)
00052 {
00053    // Set X measured in boxes units
00054 
00055    // width in pixels of pad
00056    Float_t width  = (Float_t)fPad->XtoPixel(fPad->GetX2());
00057 
00058    Coord_t x1 = ((Float_t)x)*gBoxPixelSize/width;
00059    Coord_t x2 = ((Float_t)x+1)*gBoxPixelSize/width;
00060 
00061    SetX1(x1);
00062    SetX2(x2);
00063    fX = x;
00064 }
00065 
00066 void TetrisBox::SetY(Int_t y)
00067 {
00068    // Set Y measured in boxes units
00069 
00070    // height in pixels of pad
00071    Float_t height = (Float_t)fPad->YtoPixel(fPad->GetY1());
00072 
00073    Coord_t y1 = ((Float_t)y)*gBoxPixelSize/height;
00074    Coord_t y2 = ((Float_t)y+1)*gBoxPixelSize/height;
00075 
00076    SetY1(y1);
00077    SetY2(y2);
00078    fY = y;
00079 }
00080 
00081 void TetrisBox::Paint(Option_t *option)
00082 {
00083    // Paint box if it's not hidden.
00084 
00085    if (!IsHidden() && fPad) TWbox::Paint(option);
00086 }
00087 
00088 void TetrisBox::Erase()
00089 {
00090    // erase box
00091 
00092    Double_t fX1sav = fX1;
00093    Double_t fY1sav = fY1;
00094    Double_t fX2sav = fX2;
00095    Double_t fY2sav = fY2;
00096 
00097    // erase 2 pix extra
00098    fX1 = fX1-fPad->PixeltoX(2);
00099    fY1 = fY1+fPad->PixeltoY(2);
00100    fX2 = fX2+fPad->PixeltoX(2);
00101    fY2 = fY2-fPad->PixeltoY(2);
00102 
00103    SetFillColor(fPad->GetFillColor());
00104    SetBorderMode(0);
00105    Paint();
00106 
00107    fX1 = fX1sav;
00108    fY1 = fY1sav;
00109    fX2 = fX2sav;
00110    fY2 = fY2sav;
00111 }
00112 
00113 
00114 ///////////////////////////////////////////////////////////////////
00115 //  TetrisPiece - tetris piece is set of up to 4 TetrisBoxes
00116 ///////////////////////////////////////////////////////////////////
00117 static Int_t gPieceTypes[10][4][2] = {
00118                                       {{-1,1},   //   *
00119                                        {-1,0},   //   * *
00120                                        { 0,0},   //     *
00121                                        { 0,-1}},
00122 
00123                                       {{ 1, 1},  //    *
00124                                        { 1, 0},  //  * *
00125                                        { 0, 0},  //  *
00126                                        { 0,-1}},
00127 
00128                                       {{ 0, 1},  //   *
00129                                        { 0, 0},  //   *
00130                                        { 0,-1},  //   *
00131                                        { 0,-2}}, //   *
00132 
00133                                       {{ 0, 1},  //    *
00134                                        { 1, 0},  //  * * *
00135                                        { 0, 0},
00136                                        { -1,0}},
00137 
00138                                       {{ 1, 1},  //  * *
00139                                        { 0, 1},  //  * *
00140                                        { 1, 0},  //
00141                                        { 0, 0}}, //
00142 
00143                                       {{ 0, 1},   //   *
00144                                        { 0, 0},   //   *
00145                                        { 0,-1},   // * *
00146                                        { -1,-1}},
00147 
00148                                       {{ 0, 1},   //  *
00149                                        { 0, 0},   //  *
00150                                        { 0,-1},   //  * *
00151                                        { 1,-1}},
00152 
00153                                       {{ 0, 1},    // *
00154                                        { 0, 1},    //      hidden
00155                                        { 0, 1},    //      hidden
00156                                        { 0, 1}},   //      hidden
00157 
00158                                       {{ 0, 1},   //  *
00159                                        { 0, 0},   //  *
00160                                        { 0, 1},   //       hidden
00161                                        { 0, 0}},  //       hidden
00162 
00163                                       {{ 0, 1},   //   *
00164                                        { 0, 0},   //   *
00165                                        { 0,-1},   //   *
00166                                        { 0, 0}}}; //       hidden
00167 
00168 static Color_t gPieceColors[10] = { 2,3,4,5,6,7,13,9,28,41 };
00169 
00170 
00171 TetrisPiece::~TetrisPiece()
00172 {
00173    // Clean up piece.
00174 
00175    for (int i = 0; i < 4; i++) delete fBoxes[i];
00176 }
00177 
00178 void TetrisPiece::Initialize(UInt_t type, TPad* pad)
00179 {
00180    for (int i = 0; i < 4; i++) fBoxes[i] = new TetrisBox(0,0,0,pad);
00181    fX = 0;
00182    fY = 0;
00183    SetType(type);
00184 }
00185 
00186 void TetrisPiece::SetType(UInt_t type)
00187 {
00188    // re-initialization
00189 
00190    if (type < 1 || type > 10)
00191       type = 9;
00192 
00193    for (int i = 0 ; i < 4 ; i++) {
00194       fBoxes[i]->SetType(type);
00195       fBoxes[i]->SetFillColor(gPieceColors[type-1]);
00196       fBoxes[i]->SetX(gPieceTypes[type-1][i][0]+fX);
00197       fBoxes[i]->SetY(gPieceTypes[type-1][i][1]+fY);
00198    }
00199    HideSomeBoxes(type);
00200    fType = type;
00201 }
00202 
00203 void TetrisPiece::HideSomeBoxes(UInt_t type)
00204 {
00205    // Make invisible some boxes for 1,2,3 length pieces
00206 
00207    switch(type) {
00208       case 8:  fBoxes[1]->Hide();
00209       case 9:  fBoxes[2]->Hide();
00210       case 10: fBoxes[3]->Hide();
00211       default: return;
00212    }
00213 }
00214 
00215 Bool_t TetrisPiece::RotateRight()
00216 {
00217    // Rotate anticlockwise  around (fX,fY) point
00218 
00219    // don't rotate square pieces
00220    if (GetType() == 5 || GetType() == 8) return kFALSE;
00221 
00222    Int_t tmp;
00223 
00224    for (int i = 0 ; i < 4 ; i++) {
00225       tmp = GetXx(i);
00226       SetXx(i,-GetYy(i));
00227       SetYy(i,tmp);
00228    }
00229    return kTRUE;
00230 }
00231 
00232 Bool_t TetrisPiece::RotateLeft()
00233 {
00234    // Rotate clockwise  around (fX,fY) point
00235 
00236    // don't rotate square pieces
00237    if (GetType() == 5 || GetType() == 8) return kFALSE;
00238 
00239    Int_t tmp;
00240 
00241    for (int i = 0 ; i < 4 ; i++) {
00242       tmp = GetXx(i);
00243       SetXx(i,GetYy(i));
00244       SetYy(i,-tmp);
00245    }
00246    return kTRUE;
00247 }
00248 
00249 void  TetrisPiece::Hide()
00250 {
00251    // Hide this piece
00252 
00253    for (int i = 0 ; i < 4 ; i++) {
00254       fBoxes[i]->Hide();
00255    }
00256 }
00257 
00258 void  TetrisPiece::Show()
00259 {
00260    // Show this piece
00261 
00262    for (int i = 0 ; i < 4 ; i++) {
00263       fBoxes[i]->SetType(fType);
00264    }
00265    HideSomeBoxes(fType);
00266 }
00267 
00268 void  TetrisPiece::SetX(Int_t x)
00269 {
00270    // Change of X position of the whole piece
00271 
00272    for (int i = 0 ; i < 4 ; i++) SetX(i,x+GetXx(i));
00273    fX = x;
00274 }
00275 
00276 void TetrisPiece::SetY(Int_t y)
00277 {
00278    // Change of Y position of the whole piece
00279 
00280    for (int i = 0 ; i < 4 ; i++) SetY(i,y+GetYy(i));
00281    fY = y;
00282 }
00283 
00284 void TetrisPiece::SetXY(Int_t x,Int_t y)
00285 {
00286    // Change of X,Y position of the whole piece
00287 
00288    for (int i = 0 ; i < 4 ; i++) {
00289       SetX(i,x+GetXx(i));
00290       SetY(i,y+GetYy(i));
00291    }
00292    fX = x;
00293    fY = y;
00294 }
00295 
00296 
00297 ///////////////////////////////////////////////////////////////////
00298 //  CurrentPiece =  TetrisPiece + TTimer = live TetrisPiece
00299 ///////////////////////////////////////////////////////////////////
00300 CurrentPiece::CurrentPiece(UInt_t type,TetrisBoard* board) :
00301    TetrisPiece(type,board), TTimer(1000,kTRUE)
00302 {
00303    // Initialize new piece
00304 
00305    fBoard = board;
00306 
00307    Int_t line      = fBoard->GetHeight()-2;
00308    Int_t xPosition = fBoard->GetWidth()/2;
00309 
00310    SetXY(xPosition,line);
00311 
00312    if (!CanMoveTo(xPosition,line))    { gTetris->StopGame(); return; }
00313 
00314    fBoard->Modified();
00315    fBoard->Update();
00316    fBoard->SetDropped(kFALSE);
00317    SetSpeed();       // set speed of moving according to game level
00318    Start();          // add this timer to sytem timers list = start moving
00319 }
00320 
00321 void CurrentPiece::MoveTo(int x, int y)
00322 {
00323    // Move this to (x,y) and  draw it there
00324 
00325    Erase();
00326    SetXY(x,y);            // set new coordinates
00327    fBoard->Modified();    // drawing
00328    fBoard->Update();
00329 }
00330 
00331 Bool_t CurrentPiece::CanMoveTo(int x, int y)
00332 {
00333    // Can move this piece to (x,y)?
00334 
00335    Bool_t return_value;
00336 
00337    int  savX = fX;
00338    int  savY = fY;
00339 
00340    SetXY(x,y);                    // set new coordinates
00341    return_value = CanPosition();  // if inside board and no non-zero squares underneath
00342    SetXY(savX,savY);              // go back
00343 
00344    return return_value;
00345 }
00346 
00347 Bool_t CurrentPiece::CanPosition()
00348 {
00349    // Check if piece position is allowed
00350 
00351    int x, y;
00352 
00353    for (int i = 0 ; i < 4 ; i++) {
00354       GetXY(i,x,y);      // coordinates of piece boxes at test position
00355       if (x < 0 || x >= fBoard->GetWidth()  ||
00356           y < 0 || y >= fBoard->GetHeight() ||
00357           !fBoard->IsEmpty(x,y))          return kFALSE;
00358    }
00359    return kTRUE;      // Inside board and no non-zero squares underneath.
00360 }
00361 
00362 Bool_t CurrentPiece::RotateRight()
00363 {
00364    // Rotate clockwise. Returns kTRUE if succeeded.
00365 
00366    Bool_t return_value;
00367 
00368    Erase();
00369    TetrisPiece::RotateRight();
00370    return_value = CanPosition();
00371    if (!return_value) TetrisPiece::RotateLeft();    // rotate back
00372 
00373    fBoard->Modified();    // drawing
00374    fBoard->Update();
00375    return return_value;
00376 }
00377 
00378 Bool_t CurrentPiece::RotateLeft()
00379 {
00380    // Rotate anti clockwise. Returns kTRUE if succeeded.
00381 
00382    Bool_t return_value;
00383 
00384    Erase();
00385    TetrisPiece::RotateLeft();
00386    return_value = CanPosition();
00387    if (!return_value) TetrisPiece::RotateRight();     // rotate back
00388 
00389    fBoard->Modified();    // drawing
00390    fBoard->Update();
00391    return return_value;
00392 }
00393 
00394 Bool_t CurrentPiece::OneLineDown()
00395 {
00396    // Move one line down. Returns kTRUE if succeeded.
00397 
00398    int y = GetY();
00399    int x = GetX();
00400 
00401    y--;
00402    if (!CanMoveTo(x,y))  return kFALSE;
00403 
00404    MoveTo(x,y);
00405    return kTRUE;
00406 }
00407 
00408 Bool_t CurrentPiece::DropDown()
00409 {
00410    // Move the piece to lowest allowed line. Returns kTRUE if succeeded.
00411 
00412    int y = GetY();
00413    int x = GetX();
00414    int dropHeight = 0;
00415 
00416    while (CanMoveTo(x,--y)) dropHeight++;  //  find lower allowed line
00417 
00418    y++;
00419    MoveTo(x,y);         //  .. and move to
00420    Stop();              //  stop moving
00421    fBoard->PieceDropped(this, dropHeight);
00422    return kTRUE;
00423 }
00424 
00425 Bool_t CurrentPiece::MoveLeft(int steps)
00426 {
00427    // Move piece to the left. Return kTRUE if succeeded.
00428 
00429    int y = GetY();
00430    int x = GetX();
00431 
00432    while(steps) {
00433       if (!CanMoveTo(--x ,y)) return kFALSE;  // can't move
00434       MoveTo(x,y);
00435       steps--;
00436    }
00437    return kTRUE;
00438 }
00439 
00440 Bool_t CurrentPiece::MoveRight(int steps)
00441 {
00442    // Move piece to the right. Return kTRUE if succeeded.
00443 
00444    int y = GetY();
00445    int x = GetX();
00446 
00447    while(steps) {
00448       if (!CanMoveTo(++x,y)) return kFALSE;  // can't move
00449       MoveTo(x,y);
00450       steps--;
00451    }
00452    return kTRUE;
00453 }
00454 
00455 Bool_t CurrentPiece::Notify()
00456 {
00457    // Actions after time out.
00458 
00459    if (OneLineDown()) {
00460       TTimer::Reset();
00461       return kFALSE;
00462    } else {
00463       Stop();                        // stop moving
00464       fBoard->PieceDropped(this,0);  // piece can't move -> stop moving update state of TetrisBoard
00465       return kTRUE;
00466   }
00467 }
00468 
00469 void CurrentPiece::SetSpeed()
00470 {
00471    // Set speed according to level.
00472 
00473    const Int_t factor = 2;
00474    SetTime(1000/(1 + gTetris->GetLevel()*factor));
00475 }
00476 
00477 void  CurrentPiece::Paint(Option_t*)
00478 {
00479    // Paint it in fBoard.
00480 
00481    TPad* padsav = (TPad*)TVirtualPad::Pad();
00482    fBoard->cd();
00483 
00484    for (int i = 0 ; i < 4 ; i++) {
00485       fBoxes[i]->SetBorderMode(1);
00486       fBoxes[i]->SetFillColor(gPieceColors[fType-1]);
00487       fBoxes[i]->Paint();
00488    }
00489    padsav->cd();
00490 }
00491 
00492 void CurrentPiece::Erase()
00493 {
00494    // Erase = paint with the same FillColor as fBoard has
00495 
00496    TPad* padsav = (TPad*)TVirtualPad::Pad();
00497    fBoard->cd();
00498 
00499    for (int i = 0 ; i < 4 ; i++) {
00500       fBoxes[i]->Erase();
00501    }
00502    padsav->cd();
00503 }
00504 
00505 
00506 ///////////////////////////////////////////////////////////////////
00507 //  Game  board
00508 ///////////////////////////////////////////////////////////////////
00509 TetrisBoard::TetrisBoard(Float_t xlow, Float_t ylow,Float_t xup,Float_t yup) :
00510    TPad("tetris_board","Tetris Board",xlow,ylow,xup,yup,17,4,-1)
00511 {
00512    // Game board constructor.
00513 
00514    fWidth  = (int)(fMother->XtoAbsPixel(GetX2())*(xup-xlow))/gBoxPixelSize;
00515    fHeight = (int)(fMother->YtoAbsPixel(GetY1())*(yup-ylow))/gBoxPixelSize;
00516    Double_t box = fMother->PixeltoX(gBoxPixelSize);
00517    Double_t xx = xlow + box*fWidth;
00518 
00519    if (xx<xup) {
00520       xx += fMother->PixeltoX(1);
00521       SetPad(xlow, ylow, xx, yup);
00522    }
00523 
00524    fBoard = new TetrisBoxPtr[fWidth*fHeight];
00525    fFilledLines = 0;
00526    Clear();
00527 }
00528 
00529 void TetrisBoard::Clear(Option_t *)
00530 {
00531    // Delete/clear all objects.
00532 
00533    GetListOfPrimitives()->Delete();   // delete all object in this pad (including TetrisPiece)
00534 
00535    for (int i = 0; i < fWidth; i++)
00536       for (int j = 0; j < fHeight; j++)
00537          Board(i,j) = 0;              // clear board map
00538 
00539    fIsDropped = kTRUE;
00540 }
00541 
00542 void TetrisBoard::Hide()
00543 {
00544    // Hide all objects.
00545 
00546    TetrisBox *box;
00547    TIter nextin(GetListOfPrimitives());
00548 
00549    while ((box = (TetrisBox*)nextin())) box->Hide();
00550    Modified();
00551    Update();
00552 }
00553 
00554 void TetrisBoard::Show()
00555 {
00556    // Show all objects
00557 
00558    TetrisBox *box;
00559    TIter nextin(GetListOfPrimitives());
00560 
00561    while ((box = (TetrisBox*)nextin())) box->Show();
00562    Modified();
00563    Update();
00564 }
00565 
00566 Bool_t TetrisBoard::IsFullLine(Int_t line)
00567 {
00568    // Check if line is full.
00569 
00570    Bool_t return_value = kTRUE;
00571 
00572    for (int i = 0; i < fWidth; i++)
00573       return_value = return_value && !IsEmpty(i,line);
00574 
00575    return return_value;
00576 }
00577 
00578 Bool_t TetrisBoard::IsEmptyLine(Int_t line)
00579 {
00580    // Check if line is empty
00581 
00582    Bool_t return_value = kTRUE;
00583 
00584    for (int i = 0; i < fWidth; i++)
00585       return_value = return_value && IsEmpty(i,line);
00586 
00587    return return_value;
00588 }
00589 
00590 void TetrisBoard::RemoveLine(Int_t line)
00591 {
00592    // Remove all TetrisBoxes of the line
00593 
00594    for (int i=0; i<fWidth; i++) {
00595       if (Board(i,line))  // when you delete TObject it's also removed from Pad
00596       delete Board(i,line);
00597 
00598       Board(i,line) = 0;
00599    }
00600 }
00601 
00602 void TetrisBoard::MoveOneLineDown(Int_t line)
00603 {
00604    // All  boxes of this line move to (line-1)
00605 
00606    if (!line) return;   // don't move line==0
00607 
00608    for (int i = 0; i < fWidth; i++) {
00609       if (!IsEmpty(i,line)) {
00610          Board(i,line)->MoveOneLineDown();     // change  position of Boxes
00611          Board(i,line-1) = Board(i,line);      // remapping
00612       }
00613       Board(i,line)=0;   // this line become empty
00614    }
00615    Modified();
00616    Update();
00617 }
00618 
00619 void TetrisBoard::RemoveFullLines()
00620 {
00621    // Remove full lines
00622 
00623    for (int i = 0; i < fFilledLines; i++) {
00624       while (IsFullLine(i)) {
00625          RemoveLine(i);
00626          gTetris->UpdateLinesRemoved();
00627          AllAboveLinesDown(i);
00628          fFilledLines--;
00629       }
00630    }
00631 }
00632 
00633 void  TetrisBoard::GluePiece(TetrisPiece* piece)
00634 {
00635    // Add pointers to piece boxes to fBoard::fBoard
00636 
00637    int x,y;
00638    TetrisBox *box;
00639 
00640    for (int i = 0 ; i < 4 ; i++) {
00641      piece->GetXY(i,x,y);
00642      box = piece->GetTetrisBox(i);
00643      if (box->IsHidden()) { delete  box; continue;}     // delete hidden boxes
00644      Board(x,y) = piece->GetTetrisBox(i);     // add pointers to piece boxes to board map
00645      if (y>fFilledLines) fFilledLines = y+1;  // update number of non empty lines
00646    }
00647 }
00648 
00649 void TetrisBoard::PieceDropped(TetrisPiece* piece, int height)
00650 {
00651    // Actions after piece was droped
00652 
00653    Int_t add2score = height*gTetris->GetLevel() + 10;    // update score policy (could be modified)
00654 
00655    fIsDropped = kTRUE;
00656    GluePiece(piece);
00657    RemoveFullLines();
00658    //Print();             // possible printig of board map on the terminal
00659 
00660    gTetris->UpdatePiecesDropped();
00661    gTetris->UpdateScore(add2score);
00662    gTetris->CreateNewPiece();        // create new CurrentPiece
00663    fIsDropped = kFALSE;
00664 }
00665 
00666 void TetrisBoard::Print(const char *) const
00667 {
00668    // Used for testing
00669 
00670    printf("\n");
00671 
00672    for (int j = fHeight-1; j > -1; j--) {
00673       for (int i = 0; i < fWidth; i++)
00674          ((TetrisBoard*)this)->IsEmpty(i,j) ? printf("|   ") : printf("| * ") ;
00675       printf("|\n");
00676    }
00677 }
00678 
00679 void TetrisBoard::PaintModified()
00680 {
00681    // Overload this method to acelerate graphics
00682    // (do not draw tens of heap boxes while current box is moving)
00683 
00684    if (!fIsDropped && gTetris->IsGameOn() && !gTetris->IsPaused())
00685       gTetris->fCurrentPiece->Paint();
00686    else
00687       TPad::PaintModified();
00688 }
00689 
00690 ///////////////////////////////////////////////////////////////////
00691 //  NextPiecePad
00692 //  used to show next piece.
00693 ///////////////////////////////////////////////////////////////////
00694 NextPiecePad::NextPiecePad(Float_t xlow, Float_t ylow, Float_t xup, Float_t yup)
00695    : TPad("next_piece","Next Piece Pad",xlow,ylow,xup,yup,17,4,-1)
00696 {
00697    // Next piece pad ctor.
00698 
00699    fPiece = new TetrisPiece(this);
00700    fPiece->Hide();        // hide piece at start
00701 
00702    // (how to get pixel size?)
00703    Int_t x = (int)(fMother->XtoAbsPixel(GetX2())*(xup-xlow))/gBoxPixelSize/2;
00704    Int_t y = (int)(fMother->YtoAbsPixel(GetY1())*(yup-ylow))/gBoxPixelSize/2;
00705 
00706    fPiece->SetXY(x,y);    // move to the center of pad
00707    Modified(kTRUE);
00708    Update();
00709 }
00710 
00711 
00712 ///////////////////////////////////////////////////////////////////
00713 //  PauseButton - push button
00714 //  ExecuteEvent mehtod used to pause the game
00715 ///////////////////////////////////////////////////////////////////
00716 PauseButton::PauseButton(Float_t xlow, Float_t ylow, Float_t xup, Float_t yup) :
00717    TButton("Pause"," ",xlow,ylow,xup,yup)
00718 {
00719    // Pause button constructor
00720 
00721    SetBorderSize(5);     //  decoration stuff....
00722    SetTextSize(0.45);
00723    SetFillColor(42);
00724 }
00725 
00726 void PauseButton::ExecuteEvent(Int_t event, Int_t, Int_t)
00727 {
00728    // Action after mouse click
00729 
00730    if (event == kButton1Up) {
00731       IsPressed() ? gTetris->Continue() :  gTetris->Pause();
00732       Modified(kTRUE);
00733    }
00734 }
00735 
00736 
00737 ///////////////////////////////////////////////////////////////////
00738 //  QuitButton - push button
00739 //  ExecuteEvent mehtod used to quit the game
00740 ///////////////////////////////////////////////////////////////////
00741 QuitButton::QuitButton(Float_t xlow, Float_t ylow, Float_t xup, Float_t yup) :
00742    TButton("Quit"," ",xlow,ylow,xup,yup)
00743 {
00744    // Quit button constructor
00745 
00746    SetBorderSize(5);   //  decoration stuff....
00747    SetTextSize(0.45);
00748    SetFillColor(42);
00749 }
00750 
00751 void QuitButton::ExecuteEvent(Int_t event, Int_t, Int_t)
00752 {
00753    // Action after mouse click
00754 
00755    if (event == kButton1Up) gTetris->Quit();
00756 }
00757 
00758 
00759 ///////////////////////////////////////////////////////////////////
00760 //  NewGameButton - push button
00761 //  ExecuteEvent mehtod used to start new game the game
00762 ///////////////////////////////////////////////////////////////////
00763 NewGameButton::NewGameButton(Float_t xlow, Float_t ylow, Float_t xup, Float_t yup)
00764    : TButton("New Game"," ",xlow,ylow,xup,yup)
00765 {
00766    // New game button constructor
00767 
00768    SetBorderSize(5);
00769    SetTextSize(0.45);
00770    SetFillColor(42);
00771 }
00772 
00773 void NewGameButton::ExecuteEvent(Int_t event, Int_t, Int_t)
00774 {
00775    // Ation after mouse click
00776 
00777    if (event == kButton1Up) {
00778       gTetris->NewGame();      // always starts new game
00779       Modified(kTRUE);
00780    }
00781 }
00782 
00783 
00784 ///////////////////////////////////////////////////////////////////
00785 //  InfoPad -
00786 ///////////////////////////////////////////////////////////////////
00787 InfoPad::InfoPad(const char* title, Float_t xlow, Float_t ylow, Float_t xup, Float_t yup)
00788    : TPad("info_pad",title,xlow,ylow,xup,yup,17,4,-1), TAttText(22,0,2,71,0.65)
00789 {
00790    // InfoPad constructor
00791 
00792    SetBit(kCanDelete);
00793 
00794    TText *text = new TText(xlow,yup,title);   // draw title of the information pad
00795    text->SetTextSize(0.45*(yup-ylow));
00796    text->SetY(yup+0.2*text->GetTextSize());
00797    fMother->GetListOfPrimitives()->Add(text);
00798 
00799    text = new TText(0.5,0.5,"0");          // this text used to display fValue
00800    GetListOfPrimitives()->Add(text);
00801 
00802    fValue = 0;
00803    Modified(kTRUE);
00804    Update();
00805 }
00806 
00807 void InfoPad::PaintModified()
00808 {
00809    // Actions after pad was modified (resize event, user's Modified(kTRUE) ...)
00810 
00811    char    str[40];
00812 
00813    sprintf(str,"%d",fValue);
00814 
00815    TObject *obj = GetListOfPrimitives()->First();
00816 
00817    if (obj && obj->InheritsFrom("TText")) {
00818       TText *text = (TText*)obj;
00819       text->SetTitle(str);                // set title according to fValue
00820 
00821       text->SetTextSize(GetTextSize());
00822       text->SetTextFont(GetTextFont());
00823       text->SetTextAlign(GetTextAlign());
00824       text->SetTextColor(GetTextColor());
00825       text->SetTextAngle(GetTextAngle());
00826       text->TAttText::Modify();
00827 
00828       text->SetX(0.5);        // draw centered
00829       text->SetY(0.5);
00830    }
00831    TPad::PaintModified();
00832 }
00833 
00834 
00835 ///////////////////////////////////////////////////////////////////
00836 //  KeyHandler - virtual frame used to catch and handle key events
00837 ///////////////////////////////////////////////////////////////////
00838 KeyHandler::KeyHandler() : TGFrame(gClient->GetRoot(),0,0)
00839 {
00840    // Key handler constructor.
00841 
00842    // get main frame of Tetris canvas
00843    TRootCanvas *main_frame = (TRootCanvas*)(gTetris->GetCanvasImp());
00844 
00845    // bind arrow keys and space-bar key
00846    main_frame->BindKey((const TGWindow*)this, gVirtualX->KeysymToKeycode(kKey_Up),    0);
00847    main_frame->BindKey((const TGWindow*)this, gVirtualX->KeysymToKeycode(kKey_Left),  0);
00848    main_frame->BindKey((const TGWindow*)this, gVirtualX->KeysymToKeycode(kKey_Right), 0);
00849    main_frame->BindKey((const TGWindow*)this, gVirtualX->KeysymToKeycode(kKey_Down),  0);
00850    main_frame->BindKey((const TGWindow*)this, gVirtualX->KeysymToKeycode(kKey_Space), 0);
00851 }
00852 
00853 KeyHandler::~KeyHandler()
00854 {
00855    // Cleanup key handler.
00856 
00857    // get main frame of Tetris canvas
00858    TRootCanvas *main_frame = (TRootCanvas*)(gTetris->GetCanvasImp());
00859 
00860    // remove binding of arrow keys and space-bar key
00861    main_frame->RemoveBind(this, gVirtualX->KeysymToKeycode(kKey_Up),    0);
00862    main_frame->RemoveBind(this, gVirtualX->KeysymToKeycode(kKey_Left),  0);
00863    main_frame->RemoveBind(this, gVirtualX->KeysymToKeycode(kKey_Right), 0);
00864    main_frame->RemoveBind(this, gVirtualX->KeysymToKeycode(kKey_Down),  0);
00865    main_frame->RemoveBind(this, gVirtualX->KeysymToKeycode(kKey_Space), 0);
00866    // restore key auto repeat functionality, was turned off in TGMainFrame::HandleKey()
00867    gVirtualX->SetKeyAutoRepeat(kTRUE);
00868 }
00869 
00870 
00871 Bool_t KeyHandler::HandleKey(Event_t *event)
00872 {
00873    // Handle arrow and spacebar keys
00874 
00875    char tmp[2];
00876    UInt_t keysym;
00877 
00878    gVirtualX->LookupString(event, tmp, sizeof(tmp), keysym);
00879 
00880    if (event->fType == kGKeyPress) {
00881       switch ((EKeySym)keysym) {
00882          case kKey_Left:
00883             gTetris->MoveLeft();
00884             break;
00885          case kKey_Right:
00886             gTetris->MoveRight();
00887             break;
00888          case kKey_Down:
00889             gTetris->RotateRight();
00890             break;
00891          case kKey_Up:
00892             gTetris->RotateLeft();
00893             break;
00894          case kKey_Space:
00895             gTetris->DropDown();
00896             break;
00897          default:
00898             return kTRUE;
00899       }
00900    }
00901    return kTRUE;
00902 }
00903 
00904 ///////////////////////////////////////////////////////////////////
00905 //  UpdateLevelTimer
00906 ///////////////////////////////////////////////////////////////////
00907 UpdateLevelTimer::UpdateLevelTimer(ULong_t time) : TTimer(time,kTRUE)
00908 {
00909    // Update level timer constructor
00910 
00911    SetBit(kCanDelete);   // delete this when gTetris is deleted
00912    gTetris->GetListOfPrimitives()->Add(this);
00913 }
00914 
00915 Bool_t UpdateLevelTimer::Notify()
00916 {
00917    // Actions after time out
00918 
00919    if (!gTetris->IsGameOn()) {
00920       Remove();
00921       return kTRUE;
00922    }
00923    gTetris->UpdateLevel();
00924    TTimer::Reset();
00925    return kFALSE;
00926 }
00927 
00928 
00929 ///////////////////////////////////////////////////////////////////
00930 //   Tetris =  Game manager
00931 ///////////////////////////////////////////////////////////////////
00932 Tetris::Tetris() :
00933    TCanvas("Tetris","Have a little fun with ROOT!",200,200,700,500)
00934 {
00935    // Tetris constructor
00936 
00937    gTetris = this;
00938 
00939    fCurrentPiece = 0;
00940 
00941    //-----------  play board ------------
00942    fBoard            = new  TetrisBoard(0.35,0.05,0.7,0.95);
00943    fBoard->Draw();
00944 
00945    // ----------  info pads -------------
00946    fNextPiece        =  new  NextPiecePad(0.05,0.65,0.25,0.95);
00947    fNextPiece->Draw();
00948 
00949    fLinesRemoved     =  new  InfoPad("Lines Removed",0.75,0.8,0.95,0.9);
00950    fLinesRemoved->Draw();
00951 
00952    fLevel            =  new  InfoPad("Level",0.75,0.6,0.95,0.7);
00953    fLevel->Draw();
00954 
00955    fScore            =  new  InfoPad("Score",0.75,0.4,0.95,0.5);
00956    fScore->Draw();
00957 
00958    //------------ buttons ----------------
00959    fNewGame          =  new  NewGameButton(0.05,0.05,0.25,0.15);
00960    fNewGame->Draw();
00961 
00962    fQuit             =  new  QuitButton(0.05,0.2,0.25,0.3);
00963    fQuit->Draw();
00964 
00965    fPause            =  new  PauseButton(0.05,0.35,0.25,0.45);
00966    fPause->Draw();
00967 
00968    fPiecesDropped = 0;
00969    SetFillColor(21);
00970 
00971    fKeyHandler = new KeyHandler();
00972    fUpdateLevelTimer = new UpdateLevelTimer(60000);  // every  minute
00973    SetFixedSize();
00974    Update();
00975    PrintHelpInfo();
00976    fEditable = kFALSE;
00977 }
00978 
00979 void Tetris::PrintHelpInfo()
00980 {
00981    // Prints help info
00982 
00983    printf("\n\n\n");
00984    printf("             Move   Piece Left     ---------     left-arrow\n");
00985    printf("             Move   Piece Right    ---------     right-arrow\n");
00986    printf("             Rotate Piece          ---------     up/down-arrow \n");
00987    printf("             Drop   Piece Down     ---------     space-bar\n");
00988    printf("\n\n\n");
00989 }
00990 
00991 void Tetris::CreateNewPiece()
00992 {
00993    // Create  current and next pieces
00994 
00995    UInt_t type = fNextPiece->GetPiece()->GetType();
00996    fNextPiece->NewPiece();
00997    fCurrentPiece = new CurrentPiece(type,fBoard);
00998 }
00999 
01000 void Tetris::SetFixedSize()
01001 {
01002    // Set size of canvas
01003 
01004    ((TRootCanvas*)fCanvasImp)->SetWMSizeHints(fCw,fCh+20,fCw,fCh,0,0);
01005 }
01006 
01007 void Tetris::Quit()
01008 {
01009    // Stop game and delete canvas (i.e. tetris itself)
01010 
01011    delete fKeyHandler; fKeyHandler = 0;
01012    StopGame();
01013    ((TRootCanvas*)fCanvasImp)->CloseWindow();
01014 }
01015 
01016 void Tetris::NewGame()
01017 {
01018    // Start new game
01019 
01020    gVirtualX->SetInputFocus(((TRootCanvas*)fCanvasImp)->GetId());
01021 
01022    if (IsGameOn()) StopGame();       // stop privious game
01023    fScore->Reset();
01024    fLinesRemoved->Reset();
01025    fPiecesDropped = 0;
01026    SetLevel(1);
01027    fUpdateLevelTimer->Start();
01028    fBoard->Clear();
01029    fNewGame->SetPressed(kTRUE);
01030    CreateNewPiece();                 // start game
01031 }
01032 
01033 void Tetris::StopGame()
01034 {
01035    // Stop the game
01036 
01037    fUpdateLevelTimer->Stop();
01038    if (fCurrentPiece) fCurrentPiece->Stop();
01039    fNewGame->SetPressed(kFALSE);
01040    fPause->SetPressed(kFALSE);
01041 }
01042 
01043 void Tetris::Pause()
01044 {
01045    // Pause the game
01046 
01047    if (!IsGameOn())  return;
01048    if (fCurrentPiece) fCurrentPiece->Stop();
01049    fPause->SetPressed(kTRUE);
01050    fBoard->Hide();
01051 }
01052 
01053 void  Tetris::Continue()
01054 {
01055    // Continue the game
01056 
01057    if (!IsGameOn()) return;
01058    fBoard->Show();
01059    fPause->SetPressed(kFALSE);
01060    if (fCurrentPiece) fCurrentPiece->Start();
01061 }
01062 
01063 void Tetris::MoveLeft()
01064 {
01065    // Move pice to the left
01066 
01067    if (!IsGameOn() || IsPaused() || IsWaiting())  return;
01068    fCurrentPiece->MoveLeft();
01069 }
01070 
01071 void Tetris::MoveRight()
01072 {
01073    // Move piece to the right
01074 
01075    if (!IsGameOn() || IsPaused() || IsWaiting())  return;
01076    fCurrentPiece->MoveRight();
01077 }
01078 
01079 void Tetris::DropDown()
01080 {
01081    // Drop piece down
01082 
01083    if (!IsGameOn() || IsPaused() || IsWaiting())  return;
01084    fCurrentPiece->DropDown();
01085 }
01086 
01087 void Tetris::RotateRight()
01088 {
01089    // Rotate piece right
01090 
01091    if (!IsGameOn() || IsPaused() || IsWaiting())  return;
01092    fCurrentPiece->RotateRight();
01093  }
01094 
01095 void Tetris::RotateLeft()
01096 {
01097    // Rotate piece left
01098 
01099    if (!IsGameOn() || IsPaused() || IsWaiting())  return;
01100    fCurrentPiece->RotateLeft();
01101  }
01102 
01103 void Tetris::SetLevel(int level)
01104 {
01105    // Set difficulty level
01106 
01107    fLevel->SetValue(level);
01108    if (fCurrentPiece) fCurrentPiece->SetSpeed();
01109 }

Generated on Tue Jul 5 15:16:27 2011 for ROOT_528-00b_version by  doxygen 1.5.1