|
@@ -0,0 +1,835 @@
|
|
|
|
+/*******************************************************************************************
|
|
|
|
+*
|
|
|
|
+* raylib - sample game: tetris
|
|
|
|
+*
|
|
|
|
+* Sample game Marc Palau and Ramon Santamaria
|
|
|
|
+*
|
|
|
|
+* This game has been created using raylib v1.3 (www.raylib.com)
|
|
|
|
+* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
|
|
|
|
+*
|
|
|
|
+* Copyright (c) 2015 Ramon Santamaria (@raysan5)
|
|
|
|
+*
|
|
|
|
+********************************************************************************************/
|
|
|
|
+
|
|
|
|
+#include "raylib.h"
|
|
|
|
+
|
|
|
|
+#include <stdio.h>
|
|
|
|
+#include <stdlib.h>
|
|
|
|
+#include <time.h>
|
|
|
|
+#include <math.h>
|
|
|
|
+
|
|
|
|
+#if defined(PLATFORM_WEB)
|
|
|
|
+ #include <emscripten/emscripten.h>
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+//----------------------------------------------------------------------------------
|
|
|
|
+// Some Defines
|
|
|
|
+//----------------------------------------------------------------------------------
|
|
|
|
+#define SQUARE_SIZE 30
|
|
|
|
+
|
|
|
|
+#define GRID_HORIZONTAL_SIZE 12
|
|
|
|
+#define GRID_VERTICAL_SIZE 20
|
|
|
|
+
|
|
|
|
+#define LATERAL_SPEED 10
|
|
|
|
+#define TURNING_SPEED 12
|
|
|
|
+#define FAST_FALL_AWAIT_COUNTER 30
|
|
|
|
+
|
|
|
|
+#define FADING_TIME 33
|
|
|
|
+
|
|
|
|
+//----------------------------------------------------------------------------------
|
|
|
|
+// Types and Structures Definition
|
|
|
|
+//----------------------------------------------------------------------------------
|
|
|
|
+typedef enum GridSquare { EMPTY, MOVING, FULL, BLOCK, FADING } GridSquare;
|
|
|
|
+
|
|
|
|
+//------------------------------------------------------------------------------------
|
|
|
|
+// Global Variables Declaration
|
|
|
|
+//------------------------------------------------------------------------------------
|
|
|
|
+static int screenWidth = 800;
|
|
|
|
+static int screenHeight = 620;
|
|
|
|
+
|
|
|
|
+static bool gameOver = false;
|
|
|
|
+static bool pause = false;
|
|
|
|
+
|
|
|
|
+// Matrices
|
|
|
|
+static GridSquare grid [GRID_HORIZONTAL_SIZE][GRID_VERTICAL_SIZE];
|
|
|
|
+static GridSquare piece [4][4];
|
|
|
|
+static GridSquare incomingPiece [4][4];
|
|
|
|
+
|
|
|
|
+// Theese variables keep track of the active piece position
|
|
|
|
+static int piecePositionX = 0;
|
|
|
|
+static int piecePositionY = 0;
|
|
|
|
+
|
|
|
|
+// Game parameters
|
|
|
|
+static Color fadingColor;
|
|
|
|
+//static int fallingSpeed; // In frames
|
|
|
|
+
|
|
|
|
+static bool beginPlay = true; // This var is only true at the begining of the game, used for the first matrix creations
|
|
|
|
+static bool pieceActive = false;
|
|
|
|
+static bool detection = false;
|
|
|
|
+static bool lineToDelete = false;
|
|
|
|
+
|
|
|
|
+// Statistics
|
|
|
|
+static int level = 1;
|
|
|
|
+static int lines = 0;
|
|
|
|
+
|
|
|
|
+// Counters
|
|
|
|
+static int gravityMovementCounter = 0;
|
|
|
|
+static int lateralMovementCounter = 0;
|
|
|
|
+static int turnMovementCounter = 0;
|
|
|
|
+static int fastFallMovementCounter = 0;
|
|
|
|
+
|
|
|
|
+static int fadeLineCounter = 0;
|
|
|
|
+
|
|
|
|
+// Based on level
|
|
|
|
+static int gravitySpeed = 30;
|
|
|
|
+
|
|
|
|
+//------------------------------------------------------------------------------------
|
|
|
|
+// Module Functions Declaration (local)
|
|
|
|
+//------------------------------------------------------------------------------------
|
|
|
|
+static void InitGame(void); // Initialize game
|
|
|
|
+static void UpdateGame(void); // Update game (one frame)
|
|
|
|
+static void DrawGame(void); // Draw game (one frame)
|
|
|
|
+static void UnloadGame(void); // Unload game
|
|
|
|
+static void UpdateDrawFrame(void); // Update and Draw (one frame)
|
|
|
|
+
|
|
|
|
+// Additional module functions
|
|
|
|
+static bool Createpiece();
|
|
|
|
+static void GetRandompiece();
|
|
|
|
+static void ResolveFallingMovement();
|
|
|
|
+static bool ResolveLateralMovement();
|
|
|
|
+static bool ResolveTurnMovement();
|
|
|
|
+static void CheckDetection();
|
|
|
|
+static void CheckCompletition();
|
|
|
|
+static void DeleteCompleteLines();
|
|
|
|
+
|
|
|
|
+//------------------------------------------------------------------------------------
|
|
|
|
+// Program main entry point
|
|
|
|
+//------------------------------------------------------------------------------------
|
|
|
|
+int main()
|
|
|
|
+{
|
|
|
|
+ // Initialization
|
|
|
|
+ //--------------------------------------------------------------------------------------
|
|
|
|
+ InitWindow(screenWidth, screenHeight, "sample game: tetris");
|
|
|
|
+
|
|
|
|
+ InitGame();
|
|
|
|
+
|
|
|
|
+#if defined(PLATFORM_WEB)
|
|
|
|
+ emscripten_set_main_loop(UpdateDrawFrame, 0, 1);
|
|
|
|
+#else
|
|
|
|
+
|
|
|
|
+ SetTargetFPS(60);
|
|
|
|
+ //--------------------------------------------------------------------------------------
|
|
|
|
+
|
|
|
|
+ // Main game loop
|
|
|
|
+ while (!WindowShouldClose()) // Detect window close button or ESC key
|
|
|
|
+ {
|
|
|
|
+ // Update
|
|
|
|
+ //----------------------------------------------------------------------------------
|
|
|
|
+ UpdateGame();
|
|
|
|
+ //----------------------------------------------------------------------------------
|
|
|
|
+
|
|
|
|
+ // Draw
|
|
|
|
+ //----------------------------------------------------------------------------------
|
|
|
|
+ DrawGame();
|
|
|
|
+ //----------------------------------------------------------------------------------
|
|
|
|
+ }
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+ // De-Initialization
|
|
|
|
+ //--------------------------------------------------------------------------------------
|
|
|
|
+ UnloadGame(); // Unload loaded data (textures, sounds, models...)
|
|
|
|
+
|
|
|
|
+ CloseWindow(); // Close window and OpenGL context
|
|
|
|
+ //--------------------------------------------------------------------------------------
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+//--------------------------------------------------------------------------------------
|
|
|
|
+// Game Module Functions Definition
|
|
|
|
+//--------------------------------------------------------------------------------------
|
|
|
|
+
|
|
|
|
+// Initialize game variables
|
|
|
|
+void InitGame(void)
|
|
|
|
+{
|
|
|
|
+ // Initialize game statistics
|
|
|
|
+ level = 1;
|
|
|
|
+ lines = 0;
|
|
|
|
+
|
|
|
|
+ fadingColor = GRAY;
|
|
|
|
+
|
|
|
|
+ piecePositionX = 0;
|
|
|
|
+ piecePositionY = 0;
|
|
|
|
+
|
|
|
|
+ pause = false;
|
|
|
|
+
|
|
|
|
+ beginPlay = true;
|
|
|
|
+ pieceActive = false;
|
|
|
|
+ detection = false;
|
|
|
|
+ lineToDelete = false;
|
|
|
|
+
|
|
|
|
+ // Counters
|
|
|
|
+ gravityMovementCounter = 0;
|
|
|
|
+ lateralMovementCounter = 0;
|
|
|
|
+ turnMovementCounter = 0;
|
|
|
|
+ fastFallMovementCounter = 0;
|
|
|
|
+
|
|
|
|
+ fadeLineCounter = 0;
|
|
|
|
+ gravitySpeed = 30;
|
|
|
|
+
|
|
|
|
+ // Initialize grid matrices
|
|
|
|
+ for (int i = 0; i < GRID_HORIZONTAL_SIZE; i++)
|
|
|
|
+ {
|
|
|
|
+ for (int j = 0; j < GRID_VERTICAL_SIZE; j++)
|
|
|
|
+ {
|
|
|
|
+ if ((j == GRID_VERTICAL_SIZE - 1) || (i == 0) || (i == GRID_HORIZONTAL_SIZE - 1)) grid[i][j] = BLOCK;
|
|
|
|
+ else grid[i][j] = EMPTY;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Initialize incoming piece matrices
|
|
|
|
+ for (int i = 0; i < 4; i++)
|
|
|
|
+ {
|
|
|
|
+ for (int j = 0; j< 4; j++)
|
|
|
|
+ {
|
|
|
|
+ incomingPiece[i][j] = EMPTY;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// Update game (one frame)
|
|
|
|
+void UpdateGame(void)
|
|
|
|
+{
|
|
|
|
+ if (!gameOver)
|
|
|
|
+ {
|
|
|
|
+ if (IsKeyPressed('P')) pause = !pause;
|
|
|
|
+
|
|
|
|
+ if (!pause)
|
|
|
|
+ {
|
|
|
|
+ if (!lineToDelete)
|
|
|
|
+ {
|
|
|
|
+ if (!pieceActive)
|
|
|
|
+ {
|
|
|
|
+ // Get another piece
|
|
|
|
+ pieceActive = Createpiece();
|
|
|
|
+
|
|
|
|
+ // We leave a little time before starting the fast falling down
|
|
|
|
+ fastFallMovementCounter = 0;
|
|
|
|
+ }
|
|
|
|
+ else // Piece falling
|
|
|
|
+ {
|
|
|
|
+ // Counters update
|
|
|
|
+ fastFallMovementCounter++;
|
|
|
|
+ gravityMovementCounter++;
|
|
|
|
+ lateralMovementCounter++;
|
|
|
|
+ turnMovementCounter++;
|
|
|
|
+
|
|
|
|
+ // We make sure to move if we've pressed the key this frame
|
|
|
|
+ if (IsKeyPressed(KEY_LEFT) || IsKeyPressed(KEY_RIGHT)) lateralMovementCounter = LATERAL_SPEED;
|
|
|
|
+ if (IsKeyPressed(KEY_UP)) turnMovementCounter = TURNING_SPEED;
|
|
|
|
+
|
|
|
|
+ // Fall down
|
|
|
|
+ if (IsKeyDown(KEY_DOWN) && (fastFallMovementCounter >= FAST_FALL_AWAIT_COUNTER))
|
|
|
|
+ {
|
|
|
|
+ // We make sure the piece is going to fall this frame
|
|
|
|
+ gravityMovementCounter += gravitySpeed;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (gravityMovementCounter >= gravitySpeed)
|
|
|
|
+ {
|
|
|
|
+ // Basic falling movement
|
|
|
|
+ CheckDetection(&detection);
|
|
|
|
+
|
|
|
|
+ // Check if the piece has collided with another piece or with the boundings
|
|
|
|
+ ResolveFallingMovement(&detection, &pieceActive);
|
|
|
|
+
|
|
|
|
+ // Check if we fullfilled a line and if so, erase the line and pull down the the lines above
|
|
|
|
+ CheckCompletition(&lineToDelete);
|
|
|
|
+
|
|
|
|
+ gravityMovementCounter = 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Move laterally at player's will
|
|
|
|
+ if (lateralMovementCounter >= LATERAL_SPEED)
|
|
|
|
+ {
|
|
|
|
+ // Update the lateral movement and if success, reset the lateral counter
|
|
|
|
+ if (!ResolveLateralMovement()) lateralMovementCounter = 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Turn the piece at player's will
|
|
|
|
+ if (turnMovementCounter >= TURNING_SPEED)
|
|
|
|
+ {
|
|
|
|
+ // Update the turning movement and reset the turning counter
|
|
|
|
+ if (ResolveTurnMovement()) turnMovementCounter = 0;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Game over logic
|
|
|
|
+ for (int j = 0; j < 2; j++)
|
|
|
|
+ {
|
|
|
|
+ for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++)
|
|
|
|
+ {
|
|
|
|
+ if (grid[i][j] == FULL)
|
|
|
|
+ {
|
|
|
|
+ gameOver = true;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ // Animation when deleting lines
|
|
|
|
+ fadeLineCounter++;
|
|
|
|
+
|
|
|
|
+ if (fadeLineCounter%8 < 4) fadingColor = MAROON;
|
|
|
|
+ else fadingColor = GRAY;
|
|
|
|
+
|
|
|
|
+ if (fadeLineCounter >= FADING_TIME)
|
|
|
|
+ {
|
|
|
|
+ DeleteCompleteLines();
|
|
|
|
+ fadeLineCounter = 0;
|
|
|
|
+ lineToDelete = false;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ if (IsKeyPressed(KEY_ENTER))
|
|
|
|
+ {
|
|
|
|
+ InitGame();
|
|
|
|
+ gameOver = false;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// Draw game (one frame)
|
|
|
|
+void DrawGame(void)
|
|
|
|
+{
|
|
|
|
+ BeginDrawing();
|
|
|
|
+
|
|
|
|
+ ClearBackground(RAYWHITE);
|
|
|
|
+
|
|
|
|
+ if (!gameOver)
|
|
|
|
+ {
|
|
|
|
+ // Draw gameplay area
|
|
|
|
+ Vector2 offset;
|
|
|
|
+ offset.x = screenWidth/2 - (GRID_HORIZONTAL_SIZE*SQUARE_SIZE/2);
|
|
|
|
+ offset.y = screenHeight/2 - ((GRID_VERTICAL_SIZE - 1)*SQUARE_SIZE/2) + SQUARE_SIZE*2;
|
|
|
|
+
|
|
|
|
+ offset.y -= 60; // NOTE: Harcoded position!
|
|
|
|
+
|
|
|
|
+ int controller = offset.x;
|
|
|
|
+
|
|
|
|
+ for (int j = 0; j < GRID_VERTICAL_SIZE; j++)
|
|
|
|
+ {
|
|
|
|
+ for (int i = 0; i < GRID_HORIZONTAL_SIZE; i++)
|
|
|
|
+ {
|
|
|
|
+ // Draw each square of the grid
|
|
|
|
+ if (grid[i][j] == EMPTY)
|
|
|
|
+ {
|
|
|
|
+ DrawLine(offset.x, offset.y, offset.x + SQUARE_SIZE, offset.y, LIGHTGRAY );
|
|
|
|
+ DrawLine(offset.x, offset.y, offset.x, offset.y + SQUARE_SIZE, LIGHTGRAY );
|
|
|
|
+ DrawLine(offset.x + SQUARE_SIZE, offset.y, offset.x + SQUARE_SIZE, offset.y + SQUARE_SIZE, LIGHTGRAY );
|
|
|
|
+ DrawLine(offset.x, offset.y + SQUARE_SIZE, offset.x + SQUARE_SIZE, offset.y + SQUARE_SIZE, LIGHTGRAY );
|
|
|
|
+ offset.x += SQUARE_SIZE;
|
|
|
|
+ }
|
|
|
|
+ else if (grid[i][j] == FULL)
|
|
|
|
+ {
|
|
|
|
+ DrawRectangle(offset.x, offset.y, SQUARE_SIZE, SQUARE_SIZE, GRAY);
|
|
|
|
+ offset.x += SQUARE_SIZE;
|
|
|
|
+ }
|
|
|
|
+ else if (grid[i][j] == MOVING)
|
|
|
|
+ {
|
|
|
|
+ DrawRectangle(offset.x, offset.y, SQUARE_SIZE, SQUARE_SIZE, DARKGRAY);
|
|
|
|
+ offset.x += SQUARE_SIZE;
|
|
|
|
+ }
|
|
|
|
+ else if (grid[i][j] == BLOCK)
|
|
|
|
+ {
|
|
|
|
+ DrawRectangle(offset.x, offset.y, SQUARE_SIZE, SQUARE_SIZE, LIGHTGRAY);
|
|
|
|
+ offset.x += SQUARE_SIZE;
|
|
|
|
+ }
|
|
|
|
+ else if (grid[i][j] == FADING)
|
|
|
|
+ {
|
|
|
|
+ DrawRectangle(offset.x, offset.y, SQUARE_SIZE, SQUARE_SIZE, fadingColor);
|
|
|
|
+ offset.x += SQUARE_SIZE;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ offset.x = controller;
|
|
|
|
+ offset.y += SQUARE_SIZE;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Draw incoming piece
|
|
|
|
+ //offset.x = screenWidth/2 - (4*SQUARE_SIZE/2);
|
|
|
|
+ //offset.y = (screenHeight/2 - ((GRID_VERTICAL_SIZE - 1)*SQUARE_SIZE/2)) - (3*SQUARE_SIZE);
|
|
|
|
+
|
|
|
|
+ // NOTE: Harcoded positions for the demo!
|
|
|
|
+ offset.x = 850;
|
|
|
|
+ offset.y = 75;
|
|
|
|
+
|
|
|
|
+ int controler = offset.x;
|
|
|
|
+
|
|
|
|
+ for (int j = 0; j < 4; j++)
|
|
|
|
+ {
|
|
|
|
+ for (int i = 0; i < 4; i++)
|
|
|
|
+ {
|
|
|
|
+ if (incomingPiece[i][j] == EMPTY)
|
|
|
|
+ {
|
|
|
|
+ DrawLine(offset.x, offset.y, offset.x + SQUARE_SIZE, offset.y, LIGHTGRAY );
|
|
|
|
+ DrawLine(offset.x, offset.y, offset.x, offset.y + SQUARE_SIZE, LIGHTGRAY );
|
|
|
|
+ DrawLine(offset.x + SQUARE_SIZE, offset.y, offset.x + SQUARE_SIZE, offset.y + SQUARE_SIZE, LIGHTGRAY );
|
|
|
|
+ DrawLine(offset.x, offset.y + SQUARE_SIZE, offset.x + SQUARE_SIZE, offset.y + SQUARE_SIZE, LIGHTGRAY );
|
|
|
|
+ offset.x += SQUARE_SIZE;
|
|
|
|
+ }
|
|
|
|
+ else if (incomingPiece[i][j] == MOVING)
|
|
|
|
+ {
|
|
|
|
+ DrawRectangle(offset.x, offset.y, SQUARE_SIZE, SQUARE_SIZE, GRAY);
|
|
|
|
+ offset.x += SQUARE_SIZE;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ offset.x = controler;
|
|
|
|
+ offset.y += SQUARE_SIZE;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (pause) DrawText("GAME PAUSED", screenWidth/2 - MeasureText("GAME PAUSED", 40)/2, screenHeight/2 - 40, 40, GRAY);
|
|
|
|
+ }
|
|
|
|
+ else DrawText("PRESS [ENTER] TO PLAY AGAIN", GetScreenWidth()/2 - MeasureText("PRESS [ENTER] TO PLAY AGAIN", 20)/2, GetScreenHeight()/2 - 50, 20, GRAY);
|
|
|
|
+
|
|
|
|
+ EndDrawing();
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// Unload game variables
|
|
|
|
+void UnloadGame(void)
|
|
|
|
+{
|
|
|
|
+ // TODO: Unload all dynamic loaded data (textures, sounds, models...)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// Update and Draw (one frame)
|
|
|
|
+void UpdateDrawFrame(void)
|
|
|
|
+{
|
|
|
|
+ UpdateGame();
|
|
|
|
+ DrawGame();
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+//--------------------------------------------------------------------------------------
|
|
|
|
+// Additional module functions
|
|
|
|
+//--------------------------------------------------------------------------------------
|
|
|
|
+static bool Createpiece()
|
|
|
|
+{
|
|
|
|
+ piecePositionX = (int)((GRID_HORIZONTAL_SIZE - 4)/2);
|
|
|
|
+ piecePositionY = 0;
|
|
|
|
+
|
|
|
|
+ // If the game is starting and you are going to create the first piece, we create an extra one
|
|
|
|
+ if (beginPlay)
|
|
|
|
+ {
|
|
|
|
+ GetRandompiece();
|
|
|
|
+ beginPlay = false;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // We assign the incoming piece to the actual piece
|
|
|
|
+ for (int i = 0; i < 4; i++)
|
|
|
|
+ {
|
|
|
|
+ for (int j = 0; j< 4; j++)
|
|
|
|
+ {
|
|
|
|
+ piece[i][j] = incomingPiece[i][j];
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // We assign a random piece to the incoming one
|
|
|
|
+ GetRandompiece();
|
|
|
|
+
|
|
|
|
+ // Assign the piece to the grid
|
|
|
|
+ for (int i = piecePositionX; i < piecePositionX + 4; i++)
|
|
|
|
+ {
|
|
|
|
+ for (int j = 0; j < 4; j++)
|
|
|
|
+ {
|
|
|
|
+ if (piece[i - (int)piecePositionX][j] == MOVING) grid[i][j] = MOVING;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return true;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void GetRandompiece()
|
|
|
|
+{
|
|
|
|
+ srand(time(NULL));
|
|
|
|
+ int random = rand() % 7;
|
|
|
|
+
|
|
|
|
+ for (int i = 0; i < 4; i++)
|
|
|
|
+ {
|
|
|
|
+ for (int j = 0; j < 4; j++)
|
|
|
|
+ {
|
|
|
|
+ incomingPiece[i][j] = EMPTY;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ switch(random)
|
|
|
|
+ {
|
|
|
|
+ case 0: { incomingPiece[1][1] = MOVING; incomingPiece[2][1] = MOVING; incomingPiece[1][2] = MOVING; incomingPiece[2][2] = MOVING; } break; //Cube
|
|
|
|
+ case 1: { incomingPiece[1][0] = MOVING; incomingPiece[1][1] = MOVING; incomingPiece[1][2] = MOVING; incomingPiece[2][2] = MOVING; } break; //L
|
|
|
|
+ case 2: { incomingPiece[1][2] = MOVING; incomingPiece[2][0] = MOVING; incomingPiece[2][1] = MOVING; incomingPiece[2][2] = MOVING; } break; //L inversa
|
|
|
|
+ case 3: { incomingPiece[0][1] = MOVING; incomingPiece[1][1] = MOVING; incomingPiece[2][1] = MOVING; incomingPiece[3][1] = MOVING; } break; //Recta
|
|
|
|
+ case 4: { incomingPiece[1][0] = MOVING; incomingPiece[1][1] = MOVING; incomingPiece[1][2] = MOVING; incomingPiece[2][1] = MOVING; } break; //Creu tallada
|
|
|
|
+ case 5: { incomingPiece[1][1] = MOVING; incomingPiece[2][1] = MOVING; incomingPiece[2][2] = MOVING; incomingPiece[3][2] = MOVING; } break; //S
|
|
|
|
+ case 6: { incomingPiece[1][2] = MOVING; incomingPiece[2][2] = MOVING; incomingPiece[2][1] = MOVING; incomingPiece[3][1] = MOVING; } break; //S inversa
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void ResolveFallingMovement(bool *detection, bool *pieceActive)
|
|
|
|
+{
|
|
|
|
+ // If we finished moving this piece, we stop it
|
|
|
|
+ if (*detection)
|
|
|
|
+ {
|
|
|
|
+ for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
|
|
|
|
+ {
|
|
|
|
+ for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++)
|
|
|
|
+ {
|
|
|
|
+ if (grid[i][j] == MOVING)
|
|
|
|
+ {
|
|
|
|
+ grid[i][j] = FULL;
|
|
|
|
+ *detection = false;
|
|
|
|
+ *pieceActive = false;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ // We move down the piece
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
|
|
|
|
+ {
|
|
|
|
+ for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++)
|
|
|
|
+ {
|
|
|
|
+ if (grid[i][j] == MOVING)
|
|
|
|
+ {
|
|
|
|
+ grid[i][j+1] = MOVING;
|
|
|
|
+ grid[i][j] = EMPTY;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ piecePositionY++;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static bool ResolveLateralMovement()
|
|
|
|
+{
|
|
|
|
+ bool collision = false;
|
|
|
|
+
|
|
|
|
+ // Move left
|
|
|
|
+ if (IsKeyDown(KEY_LEFT))
|
|
|
|
+ {
|
|
|
|
+ // Check if is possible to move to left
|
|
|
|
+ for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
|
|
|
|
+ {
|
|
|
|
+ for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++)
|
|
|
|
+ {
|
|
|
|
+ if (grid[i][j] == MOVING)
|
|
|
|
+ {
|
|
|
|
+ // Check if we are touching the left wall or we have a full square at the left
|
|
|
|
+ if ((i-1 == 0) || (grid[i-1][j] == FULL)) collision = true;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ // If able, move left
|
|
|
|
+ if (!collision)
|
|
|
|
+ {
|
|
|
|
+ for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
|
|
|
|
+ {
|
|
|
|
+ for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++) // We check the matrix from left to right
|
|
|
|
+ {
|
|
|
|
+ // Move everything to the left
|
|
|
|
+ if (grid[i][j] == MOVING)
|
|
|
|
+ {
|
|
|
|
+ grid[i-1][j] = MOVING;
|
|
|
|
+ grid[i][j] = EMPTY;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ piecePositionX--;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Move right
|
|
|
|
+ else if (IsKeyDown(KEY_RIGHT))
|
|
|
|
+ {
|
|
|
|
+ // Check if is possible to move to right
|
|
|
|
+ for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
|
|
|
|
+ {
|
|
|
|
+ for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++)
|
|
|
|
+ {
|
|
|
|
+ if (grid[i][j] == MOVING)
|
|
|
|
+ {
|
|
|
|
+ // Check if we are touching the right wall or we have a full square at the right
|
|
|
|
+ if ((i+1 == GRID_HORIZONTAL_SIZE - 1) || (grid[i+1][j] == FULL))
|
|
|
|
+ {
|
|
|
|
+ collision = true;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ // If able move right
|
|
|
|
+ if (!collision)
|
|
|
|
+ {
|
|
|
|
+ for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
|
|
|
|
+ {
|
|
|
|
+ for (int i = GRID_HORIZONTAL_SIZE - 1; i >= 1; i--) // We check the matrix from right to left
|
|
|
|
+ {
|
|
|
|
+ // Move everything to the right
|
|
|
|
+ if (grid[i][j] == MOVING)
|
|
|
|
+ {
|
|
|
|
+ grid[i+1][j] = MOVING;
|
|
|
|
+ grid[i][j] = EMPTY;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ piecePositionX++;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return collision;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static bool ResolveTurnMovement()
|
|
|
|
+{
|
|
|
|
+ // Input for turning the piece
|
|
|
|
+ if (IsKeyDown(KEY_UP))
|
|
|
|
+ {
|
|
|
|
+ int aux;
|
|
|
|
+ bool checker = false;
|
|
|
|
+
|
|
|
|
+ // Check all turning possibilities
|
|
|
|
+ if ((grid[piecePositionX + 3][piecePositionY] == MOVING) &&
|
|
|
|
+ (grid[piecePositionX][piecePositionY] != EMPTY) &&
|
|
|
|
+ (grid[piecePositionX][piecePositionY] != MOVING))
|
|
|
|
+ {
|
|
|
|
+ checker = true;
|
|
|
|
+ }
|
|
|
|
+ if ((grid[piecePositionX + 3][piecePositionY + 3] == MOVING) &&
|
|
|
|
+ (grid[piecePositionX + 3][piecePositionY] != EMPTY) &&
|
|
|
|
+ (grid[piecePositionX + 3][piecePositionY] != MOVING))
|
|
|
|
+ {
|
|
|
|
+ checker = true;
|
|
|
|
+ }
|
|
|
|
+ if ((grid[piecePositionX][piecePositionY + 3] == MOVING) &&
|
|
|
|
+ (grid[piecePositionX + 3][piecePositionY + 3] != EMPTY) &&
|
|
|
|
+ (grid[piecePositionX + 3][piecePositionY + 3] != MOVING))
|
|
|
|
+ {
|
|
|
|
+ checker = true;
|
|
|
|
+ }
|
|
|
|
+ if ((grid[piecePositionX][piecePositionY] == MOVING) &&
|
|
|
|
+ (grid[piecePositionX][piecePositionY + 3] != EMPTY) &&
|
|
|
|
+ (grid[piecePositionX][piecePositionY + 3] != MOVING))
|
|
|
|
+ {
|
|
|
|
+ checker = true;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ if ((grid[piecePositionX + 1][piecePositionY] == MOVING) &&
|
|
|
|
+ (grid[piecePositionX][piecePositionY + 2] != EMPTY) &&
|
|
|
|
+ (grid[piecePositionX][piecePositionY + 2] != MOVING))
|
|
|
|
+ {
|
|
|
|
+ checker = true;
|
|
|
|
+ }
|
|
|
|
+ if ((grid[piecePositionX + 3][piecePositionY + 1] == MOVING) &&
|
|
|
|
+ (grid[piecePositionX + 1][piecePositionY] != EMPTY) &&
|
|
|
|
+ (grid[piecePositionX + 1][piecePositionY] != MOVING))
|
|
|
|
+ {
|
|
|
|
+ checker = true;
|
|
|
|
+ }
|
|
|
|
+ if ((grid[piecePositionX + 2][piecePositionY + 3] == MOVING) &&
|
|
|
|
+ (grid[piecePositionX + 3][piecePositionY + 1] != EMPTY) &&
|
|
|
|
+ (grid[piecePositionX + 3][piecePositionY + 1] != MOVING))
|
|
|
|
+ {
|
|
|
|
+ checker = true;
|
|
|
|
+ }
|
|
|
|
+ if ((grid[piecePositionX][piecePositionY + 2] == MOVING) &&
|
|
|
|
+ (grid[piecePositionX + 2][piecePositionY + 3] != EMPTY) &&
|
|
|
|
+ (grid[piecePositionX + 2][piecePositionY + 3] != MOVING))
|
|
|
|
+ {
|
|
|
|
+ checker = true;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ if ((grid[piecePositionX + 2][piecePositionY] == MOVING) &&
|
|
|
|
+ (grid[piecePositionX][piecePositionY + 1] != EMPTY) &&
|
|
|
|
+ (grid[piecePositionX][piecePositionY + 1] != MOVING))
|
|
|
|
+ {
|
|
|
|
+ checker = true;
|
|
|
|
+ }
|
|
|
|
+ if ((grid[piecePositionX + 3][piecePositionY + 2] == MOVING) &&
|
|
|
|
+ (grid[piecePositionX + 2][piecePositionY] != EMPTY) &&
|
|
|
|
+ (grid[piecePositionX + 2][piecePositionY] != MOVING))
|
|
|
|
+ {
|
|
|
|
+ checker = true;
|
|
|
|
+ }
|
|
|
|
+ if ((grid[piecePositionX + 1][piecePositionY + 3] == MOVING) &&
|
|
|
|
+ (grid[piecePositionX + 3][piecePositionY + 2] != EMPTY) &&
|
|
|
|
+ (grid[piecePositionX + 3][piecePositionY + 2] != MOVING))
|
|
|
|
+ {
|
|
|
|
+ checker = true;
|
|
|
|
+ }
|
|
|
|
+ if ((grid[piecePositionX][piecePositionY + 1] == MOVING) &&
|
|
|
|
+ (grid[piecePositionX + 1][piecePositionY + 3] != EMPTY) &&
|
|
|
|
+ (grid[piecePositionX + 1][piecePositionY + 3] != MOVING))
|
|
|
|
+ {
|
|
|
|
+ checker = true;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if ((grid[piecePositionX + 1][piecePositionY + 1] == MOVING) &&
|
|
|
|
+ (grid[piecePositionX + 1][piecePositionY + 2] != EMPTY) &&
|
|
|
|
+ (grid[piecePositionX + 1][piecePositionY + 2] != MOVING))
|
|
|
|
+ {
|
|
|
|
+ checker = true;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if ((grid[piecePositionX + 2][piecePositionY + 1] == MOVING) &&
|
|
|
|
+ (grid[piecePositionX + 1][piecePositionY + 1] != EMPTY) &&
|
|
|
|
+ (grid[piecePositionX + 1][piecePositionY + 1] != MOVING))
|
|
|
|
+ {
|
|
|
|
+ checker = true;
|
|
|
|
+ }
|
|
|
|
+ if ((grid[piecePositionX + 2][piecePositionY + 2] == MOVING) &&
|
|
|
|
+ (grid[piecePositionX + 2][piecePositionY + 1] != EMPTY) &&
|
|
|
|
+ (grid[piecePositionX + 2][piecePositionY + 1] != MOVING))
|
|
|
|
+ {
|
|
|
|
+ checker = true;
|
|
|
|
+ }
|
|
|
|
+ if ((grid[piecePositionX + 1][piecePositionY + 2] == MOVING) &&
|
|
|
|
+ (grid[piecePositionX + 2][piecePositionY + 2] != EMPTY) &&
|
|
|
|
+ (grid[piecePositionX + 2][piecePositionY + 2] != MOVING))
|
|
|
|
+ {
|
|
|
|
+ checker = true;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (!checker)
|
|
|
|
+ {
|
|
|
|
+ aux = piece[0][0];
|
|
|
|
+ piece[0][0] = piece[3][0];
|
|
|
|
+ piece[3][0] = piece[3][3];
|
|
|
|
+ piece[3][3] = piece[0][3];
|
|
|
|
+ piece[0][3] = aux;
|
|
|
|
+
|
|
|
|
+ aux = piece[1][0];
|
|
|
|
+ piece[1][0] = piece[3][1];
|
|
|
|
+ piece[3][1] = piece[2][3];
|
|
|
|
+ piece[2][3] = piece[0][2];
|
|
|
|
+ piece[0][2] = aux;
|
|
|
|
+
|
|
|
|
+ aux = piece[2][0];
|
|
|
|
+ piece[2][0] = piece[3][2];
|
|
|
|
+ piece[3][2] = piece[1][3];
|
|
|
|
+ piece[1][3] = piece[0][1];
|
|
|
|
+ piece[0][1] = aux;
|
|
|
|
+
|
|
|
|
+ aux = piece[1][1];
|
|
|
|
+ piece[1][1] = piece[2][1];
|
|
|
|
+ piece[2][1] = piece[2][2];
|
|
|
|
+ piece[2][2] = piece[1][2];
|
|
|
|
+ piece[1][2] = aux;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
|
|
|
|
+ {
|
|
|
|
+ for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++)
|
|
|
|
+ {
|
|
|
|
+ if (grid[i][j] == MOVING)
|
|
|
|
+ {
|
|
|
|
+ grid[i][j] = EMPTY;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ for (int i = piecePositionX; i < piecePositionX + 4; i++)
|
|
|
|
+ {
|
|
|
|
+ for (int j = piecePositionY; j < piecePositionY + 4; j++)
|
|
|
|
+ {
|
|
|
|
+ if (piece[i - piecePositionX][j - piecePositionY] == MOVING)
|
|
|
|
+ {
|
|
|
|
+ grid[i][j] = MOVING;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return false;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void CheckDetection(bool *detection)
|
|
|
|
+{
|
|
|
|
+ for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
|
|
|
|
+ {
|
|
|
|
+ for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++)
|
|
|
|
+ {
|
|
|
|
+ if ((grid[i][j] == MOVING) && ((grid[i][j+1] == FULL) || (grid[i][j+1] == BLOCK))) *detection = true;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void CheckCompletition(bool *lineToDelete)
|
|
|
|
+{
|
|
|
|
+ int calculator;
|
|
|
|
+
|
|
|
|
+ for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
|
|
|
|
+ {
|
|
|
|
+ calculator = 0;
|
|
|
|
+ for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++)
|
|
|
|
+ {
|
|
|
|
+ // Count each square of the line
|
|
|
|
+ if (grid[i][j] == FULL)
|
|
|
|
+ {
|
|
|
|
+ calculator++;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Check if we completed the whole line
|
|
|
|
+ if (calculator == GRID_HORIZONTAL_SIZE - 2)
|
|
|
|
+ {
|
|
|
|
+ *lineToDelete = true;
|
|
|
|
+ calculator = 0;
|
|
|
|
+ // points++;
|
|
|
|
+
|
|
|
|
+ // Mark the completed line
|
|
|
|
+ for (int z = 1; z < GRID_HORIZONTAL_SIZE - 1; z++)
|
|
|
|
+ {
|
|
|
|
+ grid[z][j] = FADING;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void DeleteCompleteLines()
|
|
|
|
+{
|
|
|
|
+ // erase the completed line
|
|
|
|
+ for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
|
|
|
|
+ {
|
|
|
|
+ while (grid[1][j] == FADING)
|
|
|
|
+ {
|
|
|
|
+ for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++)
|
|
|
|
+ {
|
|
|
|
+ grid[i][j] = EMPTY;
|
|
|
|
+ }
|
|
|
|
+ for (int j2 = j-1; j2 >= 0; j2--)
|
|
|
|
+ {
|
|
|
|
+ for (int i2 = 1; i2 < GRID_HORIZONTAL_SIZE - 1; i2++)
|
|
|
|
+ {
|
|
|
|
+ if (grid[i2][j2] == FULL)
|
|
|
|
+ {
|
|
|
|
+ grid[i2][j2+1] = FULL;
|
|
|
|
+ grid[i2][j2] = EMPTY;
|
|
|
|
+ }
|
|
|
|
+ else if (grid[i2][j2] == FADING)
|
|
|
|
+ {
|
|
|
|
+ grid[i2][j2+1] = FADING;
|
|
|
|
+ grid[i2][j2] = EMPTY;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|