Advertisement
Amorf

Untitled

Dec 14th, 2021
96
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.54 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