You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

831 lines
27 KiB

  1. /*******************************************************************************************
  2. *
  3. * raylib - sample game: tetris
  4. *
  5. * Sample game Marc Palau and Ramon Santamaria
  6. *
  7. * This game has been created using raylib v1.3 (www.raylib.com)
  8. * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
  9. *
  10. * Copyright (c) 2015 Ramon Santamaria (@raysan5)
  11. *
  12. ********************************************************************************************/
  13. #include "raylib.h"
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <time.h>
  17. #include <math.h>
  18. #if defined(PLATFORM_WEB)
  19. #include <emscripten/emscripten.h>
  20. #endif
  21. //----------------------------------------------------------------------------------
  22. // Some Defines
  23. //----------------------------------------------------------------------------------
  24. #define SQUARE_SIZE 20
  25. #define GRID_HORIZONTAL_SIZE 12
  26. #define GRID_VERTICAL_SIZE 20
  27. #define LATERAL_SPEED 10
  28. #define TURNING_SPEED 12
  29. #define FAST_FALL_AWAIT_COUNTER 30
  30. #define FADING_TIME 33
  31. //----------------------------------------------------------------------------------
  32. // Types and Structures Definition
  33. //----------------------------------------------------------------------------------
  34. typedef enum GridSquare { EMPTY, MOVING, FULL, BLOCK, FADING } GridSquare;
  35. //------------------------------------------------------------------------------------
  36. // Global Variables Declaration
  37. //------------------------------------------------------------------------------------
  38. static int screenWidth = 800;
  39. static int screenHeight = 450;
  40. static bool gameOver = false;
  41. static bool pause = false;
  42. // Matrices
  43. static GridSquare grid [GRID_HORIZONTAL_SIZE][GRID_VERTICAL_SIZE];
  44. static GridSquare piece [4][4];
  45. static GridSquare incomingPiece [4][4];
  46. // Theese variables keep track of the active piece position
  47. static int piecePositionX = 0;
  48. static int piecePositionY = 0;
  49. // Game parameters
  50. static Color fadingColor;
  51. //static int fallingSpeed; // In frames
  52. static bool beginPlay = true; // This var is only true at the begining of the game, used for the first matrix creations
  53. static bool pieceActive = false;
  54. static bool detection = false;
  55. static bool lineToDelete = false;
  56. // Statistics
  57. static int level = 1;
  58. static int lines = 0;
  59. // Counters
  60. static int gravityMovementCounter = 0;
  61. static int lateralMovementCounter = 0;
  62. static int turnMovementCounter = 0;
  63. static int fastFallMovementCounter = 0;
  64. static int fadeLineCounter = 0;
  65. // Based on level
  66. static int gravitySpeed = 30;
  67. //------------------------------------------------------------------------------------
  68. // Module Functions Declaration (local)
  69. //------------------------------------------------------------------------------------
  70. static void InitGame(void); // Initialize game
  71. static void UpdateGame(void); // Update game (one frame)
  72. static void DrawGame(void); // Draw game (one frame)
  73. static void UnloadGame(void); // Unload game
  74. static void UpdateDrawFrame(void); // Update and Draw (one frame)
  75. // Additional module functions
  76. static bool Createpiece();
  77. static void GetRandompiece();
  78. static void ResolveFallingMovement();
  79. static bool ResolveLateralMovement();
  80. static bool ResolveTurnMovement();
  81. static void CheckDetection();
  82. static void CheckCompletition();
  83. static void DeleteCompleteLines();
  84. //------------------------------------------------------------------------------------
  85. // Program main entry point
  86. //------------------------------------------------------------------------------------
  87. int main(void)
  88. {
  89. // Initialization (Note windowTitle is unused on Android)
  90. //---------------------------------------------------------
  91. InitWindow(screenWidth, screenHeight, "sample game: tetris");
  92. InitGame();
  93. #if defined(PLATFORM_WEB)
  94. emscripten_set_main_loop(UpdateDrawFrame, 0, 1);
  95. #else
  96. SetTargetFPS(60);
  97. //--------------------------------------------------------------------------------------
  98. // Main game loop
  99. while (!WindowShouldClose()) // Detect window close button or ESC key
  100. {
  101. // Update and Draw
  102. //----------------------------------------------------------------------------------
  103. UpdateDrawFrame();
  104. //----------------------------------------------------------------------------------
  105. }
  106. #endif
  107. // De-Initialization
  108. //--------------------------------------------------------------------------------------
  109. UnloadGame(); // Unload loaded data (textures, sounds, models...)
  110. CloseWindow(); // Close window and OpenGL context
  111. //--------------------------------------------------------------------------------------
  112. return 0;
  113. }
  114. //--------------------------------------------------------------------------------------
  115. // Game Module Functions Definition
  116. //--------------------------------------------------------------------------------------
  117. // Initialize game variables
  118. void InitGame(void)
  119. {
  120. // Initialize game statistics
  121. level = 1;
  122. lines = 0;
  123. fadingColor = GRAY;
  124. piecePositionX = 0;
  125. piecePositionY = 0;
  126. pause = false;
  127. beginPlay = true;
  128. pieceActive = false;
  129. detection = false;
  130. lineToDelete = false;
  131. // Counters
  132. gravityMovementCounter = 0;
  133. lateralMovementCounter = 0;
  134. turnMovementCounter = 0;
  135. fastFallMovementCounter = 0;
  136. fadeLineCounter = 0;
  137. gravitySpeed = 30;
  138. // Initialize grid matrices
  139. for (int i = 0; i < GRID_HORIZONTAL_SIZE; i++)
  140. {
  141. for (int j = 0; j < GRID_VERTICAL_SIZE; j++)
  142. {
  143. if ((j == GRID_VERTICAL_SIZE - 1) || (i == 0) || (i == GRID_HORIZONTAL_SIZE - 1)) grid[i][j] = BLOCK;
  144. else grid[i][j] = EMPTY;
  145. }
  146. }
  147. // Initialize incoming piece matrices
  148. for (int i = 0; i < 4; i++)
  149. {
  150. for (int j = 0; j< 4; j++)
  151. {
  152. incomingPiece[i][j] = EMPTY;
  153. }
  154. }
  155. }
  156. // Update game (one frame)
  157. void UpdateGame(void)
  158. {
  159. if (!gameOver)
  160. {
  161. if (IsKeyPressed('P')) pause = !pause;
  162. if (!pause)
  163. {
  164. if (!lineToDelete)
  165. {
  166. if (!pieceActive)
  167. {
  168. // Get another piece
  169. pieceActive = Createpiece();
  170. // We leave a little time before starting the fast falling down
  171. fastFallMovementCounter = 0;
  172. }
  173. else // Piece falling
  174. {
  175. // Counters update
  176. fastFallMovementCounter++;
  177. gravityMovementCounter++;
  178. lateralMovementCounter++;
  179. turnMovementCounter++;
  180. // We make sure to move if we've pressed the key this frame
  181. if (IsKeyPressed(KEY_LEFT) || IsKeyPressed(KEY_RIGHT)) lateralMovementCounter = LATERAL_SPEED;
  182. if (IsKeyPressed(KEY_UP)) turnMovementCounter = TURNING_SPEED;
  183. // Fall down
  184. if (IsKeyDown(KEY_DOWN) && (fastFallMovementCounter >= FAST_FALL_AWAIT_COUNTER))
  185. {
  186. // We make sure the piece is going to fall this frame
  187. gravityMovementCounter += gravitySpeed;
  188. }
  189. if (gravityMovementCounter >= gravitySpeed)
  190. {
  191. // Basic falling movement
  192. CheckDetection(&detection);
  193. // Check if the piece has collided with another piece or with the boundings
  194. ResolveFallingMovement(&detection, &pieceActive);
  195. // Check if we fullfilled a line and if so, erase the line and pull down the the lines above
  196. CheckCompletition(&lineToDelete);
  197. gravityMovementCounter = 0;
  198. }
  199. // Move laterally at player's will
  200. if (lateralMovementCounter >= LATERAL_SPEED)
  201. {
  202. // Update the lateral movement and if success, reset the lateral counter
  203. if (!ResolveLateralMovement()) lateralMovementCounter = 0;
  204. }
  205. // Turn the piece at player's will
  206. if (turnMovementCounter >= TURNING_SPEED)
  207. {
  208. // Update the turning movement and reset the turning counter
  209. if (ResolveTurnMovement()) turnMovementCounter = 0;
  210. }
  211. }
  212. // Game over logic
  213. for (int j = 0; j < 2; j++)
  214. {
  215. for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++)
  216. {
  217. if (grid[i][j] == FULL)
  218. {
  219. gameOver = true;
  220. }
  221. }
  222. }
  223. }
  224. else
  225. {
  226. // Animation when deleting lines
  227. fadeLineCounter++;
  228. if (fadeLineCounter%8 < 4) fadingColor = MAROON;
  229. else fadingColor = GRAY;
  230. if (fadeLineCounter >= FADING_TIME)
  231. {
  232. DeleteCompleteLines();
  233. fadeLineCounter = 0;
  234. lineToDelete = false;
  235. lines++;
  236. }
  237. }
  238. }
  239. }
  240. else
  241. {
  242. if (IsKeyPressed(KEY_ENTER))
  243. {
  244. InitGame();
  245. gameOver = false;
  246. }
  247. }
  248. }
  249. // Draw game (one frame)
  250. void DrawGame(void)
  251. {
  252. BeginDrawing();
  253. ClearBackground(RAYWHITE);
  254. if (!gameOver)
  255. {
  256. // Draw gameplay area
  257. Vector2 offset;
  258. offset.x = screenWidth/2 - (GRID_HORIZONTAL_SIZE*SQUARE_SIZE/2) - 50;
  259. offset.y = screenHeight/2 - ((GRID_VERTICAL_SIZE - 1)*SQUARE_SIZE/2) + SQUARE_SIZE*2;
  260. offset.y -= 50; // NOTE: Harcoded position!
  261. int controller = offset.x;
  262. for (int j = 0; j < GRID_VERTICAL_SIZE; j++)
  263. {
  264. for (int i = 0; i < GRID_HORIZONTAL_SIZE; i++)
  265. {
  266. // Draw each square of the grid
  267. if (grid[i][j] == EMPTY)
  268. {
  269. DrawLine(offset.x, offset.y, offset.x + SQUARE_SIZE, offset.y, LIGHTGRAY );
  270. DrawLine(offset.x, offset.y, offset.x, offset.y + SQUARE_SIZE, LIGHTGRAY );
  271. DrawLine(offset.x + SQUARE_SIZE, offset.y, offset.x + SQUARE_SIZE, offset.y + SQUARE_SIZE, LIGHTGRAY );
  272. DrawLine(offset.x, offset.y + SQUARE_SIZE, offset.x + SQUARE_SIZE, offset.y + SQUARE_SIZE, LIGHTGRAY );
  273. offset.x += SQUARE_SIZE;
  274. }
  275. else if (grid[i][j] == FULL)
  276. {
  277. DrawRectangle(offset.x, offset.y, SQUARE_SIZE, SQUARE_SIZE, GRAY);
  278. offset.x += SQUARE_SIZE;
  279. }
  280. else if (grid[i][j] == MOVING)
  281. {
  282. DrawRectangle(offset.x, offset.y, SQUARE_SIZE, SQUARE_SIZE, DARKGRAY);
  283. offset.x += SQUARE_SIZE;
  284. }
  285. else if (grid[i][j] == BLOCK)
  286. {
  287. DrawRectangle(offset.x, offset.y, SQUARE_SIZE, SQUARE_SIZE, LIGHTGRAY);
  288. offset.x += SQUARE_SIZE;
  289. }
  290. else if (grid[i][j] == FADING)
  291. {
  292. DrawRectangle(offset.x, offset.y, SQUARE_SIZE, SQUARE_SIZE, fadingColor);
  293. offset.x += SQUARE_SIZE;
  294. }
  295. }
  296. offset.x = controller;
  297. offset.y += SQUARE_SIZE;
  298. }
  299. // Draw incoming piece (hardcoded)
  300. offset.x = 500;
  301. offset.y = 45;
  302. int controler = offset.x;
  303. for (int j = 0; j < 4; j++)
  304. {
  305. for (int i = 0; i < 4; i++)
  306. {
  307. if (incomingPiece[i][j] == EMPTY)
  308. {
  309. DrawLine(offset.x, offset.y, offset.x + SQUARE_SIZE, offset.y, LIGHTGRAY );
  310. DrawLine(offset.x, offset.y, offset.x, offset.y + SQUARE_SIZE, LIGHTGRAY );
  311. DrawLine(offset.x + SQUARE_SIZE, offset.y, offset.x + SQUARE_SIZE, offset.y + SQUARE_SIZE, LIGHTGRAY );
  312. DrawLine(offset.x, offset.y + SQUARE_SIZE, offset.x + SQUARE_SIZE, offset.y + SQUARE_SIZE, LIGHTGRAY );
  313. offset.x += SQUARE_SIZE;
  314. }
  315. else if (incomingPiece[i][j] == MOVING)
  316. {
  317. DrawRectangle(offset.x, offset.y, SQUARE_SIZE, SQUARE_SIZE, GRAY);
  318. offset.x += SQUARE_SIZE;
  319. }
  320. }
  321. offset.x = controler;
  322. offset.y += SQUARE_SIZE;
  323. }
  324. DrawText("INCOMING:", offset.x, offset.y - 100, 10, GRAY);
  325. DrawText(FormatText("LINES: %04i", lines), offset.x, offset.y + 20, 10, GRAY);
  326. if (pause) DrawText("GAME PAUSED", screenWidth/2 - MeasureText("GAME PAUSED", 40)/2, screenHeight/2 - 40, 40, GRAY);
  327. }
  328. else DrawText("PRESS [ENTER] TO PLAY AGAIN", GetScreenWidth()/2 - MeasureText("PRESS [ENTER] TO PLAY AGAIN", 20)/2, GetScreenHeight()/2 - 50, 20, GRAY);
  329. EndDrawing();
  330. }
  331. // Unload game variables
  332. void UnloadGame(void)
  333. {
  334. // TODO: Unload all dynamic loaded data (textures, sounds, models...)
  335. }
  336. // Update and Draw (one frame)
  337. void UpdateDrawFrame(void)
  338. {
  339. UpdateGame();
  340. DrawGame();
  341. }
  342. //--------------------------------------------------------------------------------------
  343. // Additional module functions
  344. //--------------------------------------------------------------------------------------
  345. static bool Createpiece()
  346. {
  347. piecePositionX = (int)((GRID_HORIZONTAL_SIZE - 4)/2);
  348. piecePositionY = 0;
  349. // If the game is starting and you are going to create the first piece, we create an extra one
  350. if (beginPlay)
  351. {
  352. GetRandompiece();
  353. beginPlay = false;
  354. }
  355. // We assign the incoming piece to the actual piece
  356. for (int i = 0; i < 4; i++)
  357. {
  358. for (int j = 0; j< 4; j++)
  359. {
  360. piece[i][j] = incomingPiece[i][j];
  361. }
  362. }
  363. // We assign a random piece to the incoming one
  364. GetRandompiece();
  365. // Assign the piece to the grid
  366. for (int i = piecePositionX; i < piecePositionX + 4; i++)
  367. {
  368. for (int j = 0; j < 4; j++)
  369. {
  370. if (piece[i - (int)piecePositionX][j] == MOVING) grid[i][j] = MOVING;
  371. }
  372. }
  373. return true;
  374. }
  375. static void GetRandompiece()
  376. {
  377. srand(time(NULL));
  378. int random = rand() % 7;
  379. for (int i = 0; i < 4; i++)
  380. {
  381. for (int j = 0; j < 4; j++)
  382. {
  383. incomingPiece[i][j] = EMPTY;
  384. }
  385. }
  386. switch(random)
  387. {
  388. case 0: { incomingPiece[1][1] = MOVING; incomingPiece[2][1] = MOVING; incomingPiece[1][2] = MOVING; incomingPiece[2][2] = MOVING; } break; //Cube
  389. case 1: { incomingPiece[1][0] = MOVING; incomingPiece[1][1] = MOVING; incomingPiece[1][2] = MOVING; incomingPiece[2][2] = MOVING; } break; //L
  390. case 2: { incomingPiece[1][2] = MOVING; incomingPiece[2][0] = MOVING; incomingPiece[2][1] = MOVING; incomingPiece[2][2] = MOVING; } break; //L inversa
  391. case 3: { incomingPiece[0][1] = MOVING; incomingPiece[1][1] = MOVING; incomingPiece[2][1] = MOVING; incomingPiece[3][1] = MOVING; } break; //Recta
  392. case 4: { incomingPiece[1][0] = MOVING; incomingPiece[1][1] = MOVING; incomingPiece[1][2] = MOVING; incomingPiece[2][1] = MOVING; } break; //Creu tallada
  393. case 5: { incomingPiece[1][1] = MOVING; incomingPiece[2][1] = MOVING; incomingPiece[2][2] = MOVING; incomingPiece[3][2] = MOVING; } break; //S
  394. case 6: { incomingPiece[1][2] = MOVING; incomingPiece[2][2] = MOVING; incomingPiece[2][1] = MOVING; incomingPiece[3][1] = MOVING; } break; //S inversa
  395. }
  396. }
  397. static void ResolveFallingMovement(bool *detection, bool *pieceActive)
  398. {
  399. // If we finished moving this piece, we stop it
  400. if (*detection)
  401. {
  402. for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
  403. {
  404. for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++)
  405. {
  406. if (grid[i][j] == MOVING)
  407. {
  408. grid[i][j] = FULL;
  409. *detection = false;
  410. *pieceActive = false;
  411. }
  412. }
  413. }
  414. }
  415. // We move down the piece
  416. else
  417. {
  418. for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
  419. {
  420. for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++)
  421. {
  422. if (grid[i][j] == MOVING)
  423. {
  424. grid[i][j+1] = MOVING;
  425. grid[i][j] = EMPTY;
  426. }
  427. }
  428. }
  429. piecePositionY++;
  430. }
  431. }
  432. static bool ResolveLateralMovement()
  433. {
  434. bool collision = false;
  435. // Move left
  436. if (IsKeyDown(KEY_LEFT))
  437. {
  438. // Check if is possible to move to left
  439. for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
  440. {
  441. for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++)
  442. {
  443. if (grid[i][j] == MOVING)
  444. {
  445. // Check if we are touching the left wall or we have a full square at the left
  446. if ((i-1 == 0) || (grid[i-1][j] == FULL)) collision = true;
  447. }
  448. }
  449. }
  450. // If able, move left
  451. if (!collision)
  452. {
  453. for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
  454. {
  455. for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++) // We check the matrix from left to right
  456. {
  457. // Move everything to the left
  458. if (grid[i][j] == MOVING)
  459. {
  460. grid[i-1][j] = MOVING;
  461. grid[i][j] = EMPTY;
  462. }
  463. }
  464. }
  465. piecePositionX--;
  466. }
  467. }
  468. // Move right
  469. else if (IsKeyDown(KEY_RIGHT))
  470. {
  471. // Check if is possible to move to right
  472. for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
  473. {
  474. for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++)
  475. {
  476. if (grid[i][j] == MOVING)
  477. {
  478. // Check if we are touching the right wall or we have a full square at the right
  479. if ((i+1 == GRID_HORIZONTAL_SIZE - 1) || (grid[i+1][j] == FULL))
  480. {
  481. collision = true;
  482. }
  483. }
  484. }
  485. }
  486. // If able move right
  487. if (!collision)
  488. {
  489. for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
  490. {
  491. for (int i = GRID_HORIZONTAL_SIZE - 1; i >= 1; i--) // We check the matrix from right to left
  492. {
  493. // Move everything to the right
  494. if (grid[i][j] == MOVING)
  495. {
  496. grid[i+1][j] = MOVING;
  497. grid[i][j] = EMPTY;
  498. }
  499. }
  500. }
  501. piecePositionX++;
  502. }
  503. }
  504. return collision;
  505. }
  506. static bool ResolveTurnMovement()
  507. {
  508. // Input for turning the piece
  509. if (IsKeyDown(KEY_UP))
  510. {
  511. int aux;
  512. bool checker = false;
  513. // Check all turning possibilities
  514. if ((grid[piecePositionX + 3][piecePositionY] == MOVING) &&
  515. (grid[piecePositionX][piecePositionY] != EMPTY) &&
  516. (grid[piecePositionX][piecePositionY] != MOVING))
  517. {
  518. checker = true;
  519. }
  520. if ((grid[piecePositionX + 3][piecePositionY + 3] == MOVING) &&
  521. (grid[piecePositionX + 3][piecePositionY] != EMPTY) &&
  522. (grid[piecePositionX + 3][piecePositionY] != MOVING))
  523. {
  524. checker = true;
  525. }
  526. if ((grid[piecePositionX][piecePositionY + 3] == MOVING) &&
  527. (grid[piecePositionX + 3][piecePositionY + 3] != EMPTY) &&
  528. (grid[piecePositionX + 3][piecePositionY + 3] != MOVING))
  529. {
  530. checker = true;
  531. }
  532. if ((grid[piecePositionX][piecePositionY] == MOVING) &&
  533. (grid[piecePositionX][piecePositionY + 3] != EMPTY) &&
  534. (grid[piecePositionX][piecePositionY + 3] != MOVING))
  535. {
  536. checker = true;
  537. }
  538. if ((grid[piecePositionX + 1][piecePositionY] == MOVING) &&
  539. (grid[piecePositionX][piecePositionY + 2] != EMPTY) &&
  540. (grid[piecePositionX][piecePositionY + 2] != MOVING))
  541. {
  542. checker = true;
  543. }
  544. if ((grid[piecePositionX + 3][piecePositionY + 1] == MOVING) &&
  545. (grid[piecePositionX + 1][piecePositionY] != EMPTY) &&
  546. (grid[piecePositionX + 1][piecePositionY] != MOVING))
  547. {
  548. checker = true;
  549. }
  550. if ((grid[piecePositionX + 2][piecePositionY + 3] == MOVING) &&
  551. (grid[piecePositionX + 3][piecePositionY + 1] != EMPTY) &&
  552. (grid[piecePositionX + 3][piecePositionY + 1] != MOVING))
  553. {
  554. checker = true;
  555. }
  556. if ((grid[piecePositionX][piecePositionY + 2] == MOVING) &&
  557. (grid[piecePositionX + 2][piecePositionY + 3] != EMPTY) &&
  558. (grid[piecePositionX + 2][piecePositionY + 3] != MOVING))
  559. {
  560. checker = true;
  561. }
  562. if ((grid[piecePositionX + 2][piecePositionY] == MOVING) &&
  563. (grid[piecePositionX][piecePositionY + 1] != EMPTY) &&
  564. (grid[piecePositionX][piecePositionY + 1] != MOVING))
  565. {
  566. checker = true;
  567. }
  568. if ((grid[piecePositionX + 3][piecePositionY + 2] == MOVING) &&
  569. (grid[piecePositionX + 2][piecePositionY] != EMPTY) &&
  570. (grid[piecePositionX + 2][piecePositionY] != MOVING))
  571. {
  572. checker = true;
  573. }
  574. if ((grid[piecePositionX + 1][piecePositionY + 3] == MOVING) &&
  575. (grid[piecePositionX + 3][piecePositionY + 2] != EMPTY) &&
  576. (grid[piecePositionX + 3][piecePositionY + 2] != MOVING))
  577. {
  578. checker = true;
  579. }
  580. if ((grid[piecePositionX][piecePositionY + 1] == MOVING) &&
  581. (grid[piecePositionX + 1][piecePositionY + 3] != EMPTY) &&
  582. (grid[piecePositionX + 1][piecePositionY + 3] != MOVING))
  583. {
  584. checker = true;
  585. }
  586. if ((grid[piecePositionX + 1][piecePositionY + 1] == MOVING) &&
  587. (grid[piecePositionX + 1][piecePositionY + 2] != EMPTY) &&
  588. (grid[piecePositionX + 1][piecePositionY + 2] != MOVING))
  589. {
  590. checker = true;
  591. }
  592. if ((grid[piecePositionX + 2][piecePositionY + 1] == MOVING) &&
  593. (grid[piecePositionX + 1][piecePositionY + 1] != EMPTY) &&
  594. (grid[piecePositionX + 1][piecePositionY + 1] != MOVING))
  595. {
  596. checker = true;
  597. }
  598. if ((grid[piecePositionX + 2][piecePositionY + 2] == MOVING) &&
  599. (grid[piecePositionX + 2][piecePositionY + 1] != EMPTY) &&
  600. (grid[piecePositionX + 2][piecePositionY + 1] != MOVING))
  601. {
  602. checker = true;
  603. }
  604. if ((grid[piecePositionX + 1][piecePositionY + 2] == MOVING) &&
  605. (grid[piecePositionX + 2][piecePositionY + 2] != EMPTY) &&
  606. (grid[piecePositionX + 2][piecePositionY + 2] != MOVING))
  607. {
  608. checker = true;
  609. }
  610. if (!checker)
  611. {
  612. aux = piece[0][0];
  613. piece[0][0] = piece[3][0];
  614. piece[3][0] = piece[3][3];
  615. piece[3][3] = piece[0][3];
  616. piece[0][3] = aux;
  617. aux = piece[1][0];
  618. piece[1][0] = piece[3][1];
  619. piece[3][1] = piece[2][3];
  620. piece[2][3] = piece[0][2];
  621. piece[0][2] = aux;
  622. aux = piece[2][0];
  623. piece[2][0] = piece[3][2];
  624. piece[3][2] = piece[1][3];
  625. piece[1][3] = piece[0][1];
  626. piece[0][1] = aux;
  627. aux = piece[1][1];
  628. piece[1][1] = piece[2][1];
  629. piece[2][1] = piece[2][2];
  630. piece[2][2] = piece[1][2];
  631. piece[1][2] = aux;
  632. }
  633. for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
  634. {
  635. for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++)
  636. {
  637. if (grid[i][j] == MOVING)
  638. {
  639. grid[i][j] = EMPTY;
  640. }
  641. }
  642. }
  643. for (int i = piecePositionX; i < piecePositionX + 4; i++)
  644. {
  645. for (int j = piecePositionY; j < piecePositionY + 4; j++)
  646. {
  647. if (piece[i - piecePositionX][j - piecePositionY] == MOVING)
  648. {
  649. grid[i][j] = MOVING;
  650. }
  651. }
  652. }
  653. return true;
  654. }
  655. return false;
  656. }
  657. static void CheckDetection(bool *detection)
  658. {
  659. for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
  660. {
  661. for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++)
  662. {
  663. if ((grid[i][j] == MOVING) && ((grid[i][j+1] == FULL) || (grid[i][j+1] == BLOCK))) *detection = true;
  664. }
  665. }
  666. }
  667. static void CheckCompletition(bool *lineToDelete)
  668. {
  669. int calculator;
  670. for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
  671. {
  672. calculator = 0;
  673. for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++)
  674. {
  675. // Count each square of the line
  676. if (grid[i][j] == FULL)
  677. {
  678. calculator++;
  679. }
  680. // Check if we completed the whole line
  681. if (calculator == GRID_HORIZONTAL_SIZE - 2)
  682. {
  683. *lineToDelete = true;
  684. calculator = 0;
  685. // points++;
  686. // Mark the completed line
  687. for (int z = 1; z < GRID_HORIZONTAL_SIZE - 1; z++)
  688. {
  689. grid[z][j] = FADING;
  690. }
  691. }
  692. }
  693. }
  694. }
  695. static void DeleteCompleteLines()
  696. {
  697. // erase the completed line
  698. for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
  699. {
  700. while (grid[1][j] == FADING)
  701. {
  702. for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++)
  703. {
  704. grid[i][j] = EMPTY;
  705. }
  706. for (int j2 = j-1; j2 >= 0; j2--)
  707. {
  708. for (int i2 = 1; i2 < GRID_HORIZONTAL_SIZE - 1; i2++)
  709. {
  710. if (grid[i2][j2] == FULL)
  711. {
  712. grid[i2][j2+1] = FULL;
  713. grid[i2][j2] = EMPTY;
  714. }
  715. else if (grid[i2][j2] == FADING)
  716. {
  717. grid[i2][j2+1] = FADING;
  718. grid[i2][j2] = EMPTY;
  719. }
  720. }
  721. }
  722. }
  723. }
  724. }