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.

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