Advertisement
Amorf

Untitled

Dec 14th, 2021
685
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.57 KB | None | 0 0
  1. #include "Level.h"
  2. #include <ctime>
  3.  
  4. Level::Level(DrawEngine &de, int width, int height) :
  5. de(de), width(width), height(height), lastTime(0.0), speed(500), score(-1)
  6. {
  7.     srand(time(0));
  8.  
  9.     // Allocate the drawing board
  10.     board = new COLORREF*[width];
  11.     for (int i = 0; i < width; i++)
  12.     {
  13.         board[i] = new COLORREF[height];
  14.         for (int j = 0; j < height; j++)
  15.             board[i][j] = RGB(0, 0, 0);
  16.     }
  17.  
  18.     // 初始化目前和下一個方塊
  19.     current = 0;
  20.     next = pieceSet.getRandomPiece();
  21. }
  22.  
  23. Level::~Level()
  24. {
  25.     for (int i = 0; i < width; i++)
  26.         delete [] board[i];
  27.     delete [] board;
  28. }
  29.  
  30. void Level::drawBoard() const
  31. {
  32.     for (int i = 0; i < width; i++)
  33.         for (int j = 0; j < height; j++)
  34.             de.drawBlock(i, j, board[i][j]);
  35. }
  36.  
  37. void Level::timerUpdate()
  38. {
  39.     // If the time isn't up, don't drop nor update
  40.     currentTime = timeGetTime();
  41.     if (currentTime - lastTime < speed)
  42.         return;
  43.  
  44.     // Time's up, drop
  45.     // If the piece hits the bottom, check if player gets score, drop the next
  46.     // piece, increase speed, redraw info
  47.     // If player gets score, increase more speed
  48.     if (current == NULL || !move(0, -1))
  49.     {
  50.         int lines = clearRows();
  51.         speed = max(speed - 2 * lines, 100);
  52.         score += 1 + lines * lines * 5;
  53.         dropRandomPiece();
  54.         drawScore();
  55.         drawSpeed();
  56.         drawNextPiece();
  57.     }
  58.  
  59.     lastTime = timeGetTime();
  60. }
  61.  
  62. bool Level::place(int x, int y, const Piece &piece)
  63. {
  64.     // Out of boundary or the position has been filled
  65.     if (x + piece.getWidth() > width || isCovered(piece, x, y))
  66.         return false;
  67.  
  68.     posX = x;
  69.     posY = y;
  70.  
  71.     POINT apt[4];
  72.     piece.getBody(apt);
  73.  
  74.     COLORREF color = piece.getColor();
  75.  
  76.     for (int i = 0; i < 4; i++)
  77.     {
  78.         if (y + apt[i].y > height - 1)
  79.             continue;
  80.         board[x+apt[i].x][y+apt[i].y] = color;
  81.     }
  82.     return true;
  83. }
  84.  
  85. bool Level::rotate()
  86. {
  87.     Piece *tmp = current;
  88.  
  89.     // Move the piece if it needs some space to rotate
  90.     int disX = max(posX + current->getHeight() - width, 0);
  91.  
  92.     // Go to next rotation state (0-3)
  93.     int rotation = (current->getRotation() + 1) % PieceSet::NUM_ROTATIONS;
  94.  
  95.     clear(*current);
  96.     current = pieceSet.getPiece(current->getId(), rotation);
  97.  
  98.     // Rotate successfully
  99.     if (place(posX - disX, posY, *current))
  100.         return true;
  101.  
  102.     // If the piece cannot rotate due to insufficient space, undo it
  103.     current = tmp;
  104.     place(posX, posY, *current);
  105.     return false;
  106. }
  107.  
  108. bool Level::move(int cxDistance, int cyDistance)
  109. {
  110.     if (posX + cxDistance < 0 || posY + cyDistance < 0 ||
  111.         posX + current->getWidth() + cxDistance > width)
  112.         return false;
  113.     if (cxDistance < 0 && isHitLeft())
  114.         return false;
  115.     if (cxDistance > 0 && isHitRight())
  116.         return false;
  117.     if (cyDistance < 0 && isHitBottom())
  118.         return false;
  119.     clear(*current);
  120.     return place(posX + cxDistance, posY + cyDistance, *current);
  121. }
  122.  
  123. void Level::clear(const Piece &piece)
  124. {
  125.     POINT apt[4];
  126.     piece.getBody(apt);
  127.     int x, y;
  128.     for (int i = 0; i < 4; i++) {
  129.         x = posX + apt[i].x;
  130.         y = posY + apt[i].y;
  131.         if (x > width -1 || y > height - 1)
  132.             continue;
  133.         board[posX+apt[i].x][posY+apt[i].y] = RGB(0,0,0);
  134.     }
  135. }
  136.  
  137. void Level::dropRandomPiece()
  138. {
  139.     current = next;
  140.     next = pieceSet.getRandomPiece();
  141.     place(3, height - 1, *current);
  142. }
  143.  
  144. bool Level::isHitBottom() const
  145. {
  146.     POINT apt[4];
  147.     int n = current->getSkirt(apt);
  148.     int x, y;
  149.     for (int i = 0; i < n; i++)
  150.     {
  151.         x = posX + apt[i].x;
  152.         y = posY + apt[i].y;
  153.         if (y < height && (y == 0 || board[x][y-1] != RGB(0,0,0)))
  154.             return true;
  155.     }
  156.     return false;
  157. }
  158.  
  159. bool Level::isHitLeft() const
  160. {
  161.     POINT apt[4];
  162.     int n = current->getLeftSide(apt);
  163.     int x, y;
  164.     for (int i = 0; i < n; i++)
  165.     {
  166.         x = posX + apt[i].x;
  167.         y = posY + apt[i].y;
  168.         if (y > height - 1)
  169.             continue;
  170.         if (x == 0 || board[x-1][y] != RGB(0,0,0))
  171.             return true;
  172.     }
  173.     return false;
  174. }
  175.  
  176. bool Level::isHitRight() const
  177. {
  178.     POINT apt[4];
  179.     int n = current->getRightSide(apt);
  180.     int x, y;
  181.     for (int i = 0; i < n; i++)
  182.     {
  183.         x = posX + apt[i].x;
  184.         y = posY + apt[i].y;
  185.         if (y > height - 1)
  186.             continue;
  187.         if (x == width - 1 || board[x+1][y] != RGB(0,0,0))
  188.             return true;
  189.     }
  190.     return false;
  191. }
  192.  
  193. bool Level::isCovered(const Piece &piece, int x, int y) const
  194. {
  195.     POINT apt[4];
  196.     piece.getBody(apt);
  197.     int tmpX, tmpY;
  198.     for (int i = 0; i < 4; i++)
  199.     {
  200.         tmpX = apt[i].x + x;
  201.         tmpY = apt[i].y + y;
  202.         if (tmpX > width - 1 || tmpY > height -1)
  203.             continue;
  204.         if (board[tmpX][tmpY] != RGB(0,0,0))
  205.             return true;
  206.     }
  207.     return false;
  208. }
  209.  
  210. int Level::clearRows()
  211. {
  212.     bool isComplete;
  213.     int rows = 0;
  214.  
  215.     for (int i = 0; i < height; i++)
  216.     {
  217.         for (int j = 0; j < width; j++)
  218.         {
  219.             if (board[j][i] == RGB(0,0,0))
  220.             {
  221.                 isComplete = false;
  222.                 break;
  223.             }
  224.             // The row is full
  225.             if (j == width - 1)
  226.                 isComplete = true;
  227.         }
  228.         // If the row is full, clear it (fill with black)
  229.         if (isComplete)
  230.         {
  231.             for (int j = 0; j < width; j++)
  232.                 board[j][i] = RGB(0,0,0);
  233.  
  234.             // Move rows down
  235.             for (int k = i; k < height - 1; k++)
  236.             {
  237.                 for (int m = 0; m < width; m++)
  238.                     board[m][k] = board[m][k+1];
  239.             }
  240.             i = -1;
  241.             rows++;
  242.         }
  243.     }
  244.     return rows;
  245. }
  246.  
  247. bool Level::isGameOver()
  248. {
  249.     // Exclude the current piece
  250.     if (current)
  251.         clear(*current);
  252.  
  253.     // If there's a piece on the top, game over
  254.     for (int i = 0; i < width; i++) {
  255.         if (board[i][height-1]) {
  256.             if (current)
  257.                 place(posX, posY, *current);
  258.             return true;
  259.         }
  260.     }
  261.  
  262.     // Put the current piece back
  263.     if (current != 0)
  264.         place(posX, posY, *current);
  265.     return false;
  266. }
  267.  
  268. void Level::drawSpeed() const
  269. {
  270.     de.drawSpeed((500 - speed) / 2, width + 1, 12);
  271. }
  272.  
  273. void Level::drawScore() const
  274. {
  275.     de.drawScore(score, width + 1, 13);
  276. }
  277.  
  278. void Level::drawNextPiece() const
  279. {
  280.     de.drawNextPiece(*next, width + 1, 14);
  281. }
  282.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement