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