summaryrefslogtreecommitdiff
path: root/TETRIS.c
diff options
context:
space:
mode:
authorAbdellah El Morabit <nsrddyn@gmail.com>2025-01-17 21:42:02 +0100
committerAbdellah El Morabit <nsrddyn@gmail.com>2025-01-17 21:42:02 +0100
commit9ff91999b122df64c910b3d7ebed1ceda949e0c0 (patch)
treee7c91ec9af16f850057238657d495938df3e2158 /TETRIS.c
parentde3d3056c8b82d868ff42362a2f6e9d2cd26a551 (diff)
collision works but overlaps
Diffstat (limited to 'TETRIS.c')
-rw-r--r--TETRIS.c307
1 files changed, 206 insertions, 101 deletions
diff --git a/TETRIS.c b/TETRIS.c
index eb0366c..fa25d04 100644
--- a/TETRIS.c
+++ b/TETRIS.c
@@ -1,27 +1,53 @@
+/*
+ * =====================================================================================
+ *
+ * Filename: Tetris.c
+ *
+ * Description: Tetris in raylib
+ *
+ * Version: 1.0
+ * Created: 01/17/2025 09:58:53
+ * Revision: 1.0
+ * Compiler: gcc
+ *
+ * Author: nsrddyn,
+ * Organization:
+ *
+ * =====================================================================================
+ */
+
#include <raylib.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
// GAME SETTINGS
-#define FPS 30
-#define FONT_SIZE 20
+#define FPS 60
+#define FONT_SIZE 10
-#define TETROMINO_SIZE 4
+#define TETROMINO_SIZE_HEIGHT 2
+#define TETROMINO_SIZE_WIDTH 4
-#define CYAN_I (Color) { 0, 255, 255, 255 }
-#define YELLOW_O (Color) { 255, 255, 102, 255 }
-#define PURPLE_T (Color) { 138, 43, 226, 255 }
-#define GREEN_S (Color) { 34, 139, 34, 255 }
-#define RED_Z (Color) { 255, 69, 0, 255 }
-#define BLUE_J (Color) { 70, 130, 180, 255 }
-#define ORANGE_L (Color) { 255, 140, 0, 255 }
+#define CYAN_I \
+ (Color) { 0, 255, 255, 255 }
+#define YELLOW_O \
+ (Color) { 255, 255, 102, 255 }
+#define PURPLE_T \
+ (Color) { 138, 43, 226, 255 }
+#define GREEN_S \
+ (Color) { 34, 139, 34, 255 }
+#define RED_Z \
+ (Color) { 255, 69, 0, 255 }
+#define BLUE_J \
+ (Color) { 70, 130, 180, 255 }
+#define ORANGE_L \
+ (Color) { 255, 140, 0, 255 }
// Window and Grid Settings
-static const int SCREEN_WIDTH = 400;
-static const int SCREEN_HEIGHT = 600;
-static const int COLUMNS = 10;
-static const int ROWS = 20;
+static const int SCREEN_WIDTH = 400;
+static const int SCREEN_HEIGHT = 600;
+static const int COLUMNS = 10; // Default standardized value for the amount of COLUMNS
+static const int ROWS = 20; // Default standardized value for the amount of ROWS
static const int CELL_WIDTH = SCREEN_WIDTH / COLUMNS;
static const int CELL_HEIGHT = SCREEN_HEIGHT / ROWS;
@@ -29,10 +55,10 @@ static int SCORE = 0;
typedef struct
{
- int blocks[TETROMINO_SIZE][TETROMINO_SIZE];
+ int blocks[TETROMINO_SIZE_HEIGHT][TETROMINO_SIZE_WIDTH];
Color color;
- int x;
- int y;
+ int x;
+ int y;
} TETROMINO;
@@ -42,55 +68,76 @@ TETROMINO TETROMINOES[7] = {
{
{0, 0, 0, 0},
{1, 1, 1, 1},
- {0, 0, 0, 0},
- {0, 0, 0, 0}},
- CYAN_I, 0, 0},
+ },
+ CYAN_I,
+ COLUMNS / 2,
+ 0},
+ // supposed to have 2 forms of rotations
+ // default spawn location is: center
{
{
{0, 1, 1, 0},
{0, 1, 1, 0},
- {0, 0, 0, 0},
- {0, 0, 0, 0}},
- YELLOW_O, 0, 0},
+ },
+ YELLOW_O,
+ COLUMNS / 2,
+ 0},
+ // supposed to have no rotation forms
+ // default spawn location is: center
{
{
{0, 1, 0, 0},
{1, 1, 1, 0},
- {0, 0, 0, 0},
- {0, 0, 0, 0}},
- PURPLE_T, 0, 0},
+ },
+ PURPLE_T,
+ 0,
+ 0},
+ // flat side left center
+ // 4 rotational forms
{
{
{0, 1, 1, 0},
{1, 1, 0, 0},
- {0, 0, 0, 0},
- {0, 0, 0, 0}},
- GREEN_S, 0, 0},
+ },
+ GREEN_S,
+ 0,
+ 0},
+ // left center
+ // 4 rotational forms
{
{
{1, 1, 0, 0},
{0, 1, 1, 0},
- {0, 0, 0, 0},
- {0, 0, 0, 0}},
- RED_Z, 0, 0},
+ },
+ RED_Z,
+ 0,
+ 0},
+ // left center
+ // 4 rotational forms
{
{
{1, 0, 0, 0},
{1, 1, 1, 0},
- {0, 0, 0, 0},
- {0, 0, 0, 0}},
- BLUE_J, 0, 0},
+ },
+ BLUE_J,
+ 0,
+ 0},
+ // flat side first and left center
+ // 4 rotational forms
{
{
{0, 0, 1, 0},
{1, 1, 1, 0},
- {0, 0, 0, 0},
- {0, 0, 0, 0}},
- ORANGE_L, 0, 0},
+ },
+ ORANGE_L,
+ 0,
+ 0},
+ // flat side first and left center
+ // 4 rotational forms
};
-void DRAW_GRID_BACKGROUND()
+void DRAW_BACKGROUND_GRID()
{
for (int i = 0; i <= COLUMNS; i++)
{
@@ -109,6 +156,7 @@ int **CREATE_TETROMINOS_GRID(int rows, int columns)
return NULL;
for (int i = 0; i < rows; i++)
+
{
array[i] = calloc(columns, sizeof(int));
if (!array[i])
@@ -122,32 +170,95 @@ int **CREATE_TETROMINOS_GRID(int rows, int columns)
return array;
}
-// detect if the active tetromino is hitting another tetromino
-int COLLISION_DETECTION(TETROMINO *ACTIVE_TETROMINO, int **GRID)
+void CHECK_FULL_LINE(int **GRID)
{
- for (int y = 0; y < TETROMINO_SIZE; y++) {
- for (int x = 0; x < TETROMINO_SIZE; x++) {
- if (ACTIVE_TETROMINO->blocks[y][x] == 1) {
- int GRID_X = ACTIVE_TETROMINO->x + x;
- int GRID_Y = ACTIVE_TETROMINO->y + y;
+ for (int y = 0; y < ROWS; y++)
+ {
+ bool FULL_LINE = true;
- if (GRID_X < 0 || GRID_X >= COLUMNS || GRID_Y >= ROWS) {
- // COLLISION
- return 1;
- }
+ for (int x = 0; x < COLUMNS; x++)
+ {
+ if (GRID[y][x] == 0)
+ {
+ FULL_LINE = false;
+ break;
+ }
+ }
- if (GRID_X >= 0 && GRID[GRID_Y][GRID_X] == 1) {
- // COLLISION
- return 1;
- }
+ if (FULL_LINE)
+ {
+ for (int i = y; i > 0; i--)
+ {
+ for (int x = 0; x < COLUMNS; x++)
+ GRID[i][x] = GRID[i - 1][x];
}
+
+ for (int x = 0; x < COLUMNS; x++)
+ GRID[ROWS - 2][x] = 0;
+
+ SCORE += 10;
}
}
+}
+
+
+
+// Detect if the active tetromino is hitting another tetromino
+int COLLISION_DETECTION(TETROMINO *tetromino, int **GRID)
+{
+
+ // FIND THE WIDTH AND HEIGHT OF THE ACTIVE TETROMINO
+
+ int CURRENT_LOWEST_INDEX_X = 0;
+ int CURRENT_LOWEST_INDEX_Y = 0;
+
+ for (int y = 0; y < TETROMINO_SIZE_HEIGHT; y++)
+ {
+ for (int x = 0; x < TETROMINO_SIZE_WIDTH; x++)
+ {
+ if (tetromino->blocks[y][x] == 1)
+ {
+ CURRENT_LOWEST_INDEX_X = x;
+ CURRENT_LOWEST_INDEX_Y = y;
+ }
+ }
+ }
+
+ for (int i = 0; i < TETROMINO_SIZE_HEIGHT; i++)
+ {
+ for (int j = 0; j < TETROMINO_SIZE_WIDTH; j++)
+ {
+ if (tetromino->blocks[i][j] == 1)
+ {
+ int GRID_X = tetromino->x + j;
+ int GRID_Y = tetromino->y + i;
+
+
+ // BLOCKS COLLISION
+ if (GRID_Y > 0 && GRID[GRID_Y][GRID_X] != 0)
+ return 1;
+ }
+ }
+ }
// NO COLLISION
return 0;
}
+int *ROTATE_ACTIVE_TETROMINO(TETROMINO *tetromino, int **GRID)
+{
+ int *ROTATED_TETROMINO;
+
+ for (int x = 0; x < COLUMNS; x++)
+ {
+ for (int y = 0; y < ROWS; y++)
+ {
+ ROTATED_TETROMINO = 0;
+ }
+ }
+ return ROTATED_TETROMINO;
+}
+
void FREE_GRID(int **array, int rows)
{
for (int i = 0; i < rows; i++)
@@ -157,17 +268,17 @@ void FREE_GRID(int **array, int rows)
void DRAW_TETROMINO(TETROMINO *tetromino)
{
- for (int y = 0; y < TETROMINO_SIZE; y++)
+ for (int y = 0; y < TETROMINO_SIZE_HEIGHT; y++)
{
- for (int x = 0; x < TETROMINO_SIZE; x++)
+ for (int x = 0; x < TETROMINO_SIZE_WIDTH; x++)
{
if (tetromino->blocks[y][x] == 1)
{
DrawRectangle(
- (tetromino->x + x) * CELL_WIDTH,
- (tetromino->y + y) * CELL_HEIGHT,
- CELL_WIDTH, CELL_HEIGHT,
- tetromino->color);
+ (tetromino->x + x) * CELL_WIDTH,
+ (tetromino->y + y) * CELL_HEIGHT,
+ CELL_WIDTH, CELL_HEIGHT,
+ tetromino->color);
}
}
}
@@ -177,29 +288,33 @@ TETROMINO SPAWN_TETROMINO()
{
int RANDOM_INDEX = GetRandomValue(0, 6);
TETROMINO tetromino = TETROMINOES[RANDOM_INDEX];
- tetromino.x = COLUMNS / 2 - 2;
- tetromino.y = 0;
+
+ if (tetromino.x == 0)
+ {
+ tetromino.x = COLUMNS / 2 - 2;
+ tetromino.y = 0;
+ }
return tetromino;
}
void MOVE_TETROMINO(TETROMINO *tetromino, int **GRID)
{
- if (!IsKeyDown(KEY_LEFT_SHIFT) && COLLISION_DETECTION(tetromino, GRID) == 0)
- {
- if (IsKeyDown(KEY_RIGHT) && tetromino->x + TETROMINO_SIZE < COLUMNS)
- tetromino->x++;
- if (IsKeyDown(KEY_LEFT) && tetromino->x > 0)
- tetromino->x--;
- if (IsKeyDown(KEY_DOWN) && tetromino->y < ROWS - 2 )
- tetromino->y++;
- }
+ // RIGHT WALL COLLISION DETECTION BY STOPPING MOVEMENT
+ if (IsKeyDown(KEY_RIGHT) && COLLISION_DETECTION(tetromino, GRID) == 0 && tetromino->x < COLUMNS - 2)
+ tetromino->x++;
+ // LEFT WALL COLLISION DETECTION BY STOPPING MOVEMENT
+ if (IsKeyDown(KEY_LEFT) && COLLISION_DETECTION(tetromino, GRID) == 0 && tetromino->x > 0)
+ tetromino->x--;
+ // BOTTOM ROW COLLISION DETECTION BY STOPPING MOVEMENT
+ if (IsKeyDown(KEY_DOWN) && COLLISION_DETECTION(tetromino, GRID) == 0 && tetromino->y < ROWS - 2)
+ tetromino->y++;
}
void SAVE_TETROMINO(TETROMINO *tetromino, int **GRID)
{
- for (int y = 0; y < TETROMINO_SIZE; y++)
+ for (int y = 0; y < TETROMINO_SIZE_HEIGHT; y++)
{
- for (int x = 0; x < TETROMINO_SIZE; x++)
+ for (int x = 0; x < TETROMINO_SIZE_WIDTH; x++)
{
if (tetromino->blocks[y][x] == 1)
{
@@ -219,7 +334,7 @@ void DRAW_SAVED_TETROMINO(int **GRID, TETROMINO *tetromino)
for (int x = 0; x < COLUMNS; x++)
{
if (GRID[y][x] == 1)
- DrawRectangle((x * CELL_WIDTH) , (y * CELL_HEIGHT) , CELL_WIDTH, CELL_HEIGHT, tetromino->color);
+ DrawRectangle((x * CELL_WIDTH), (y * CELL_HEIGHT), CELL_WIDTH, CELL_HEIGHT, tetromino->color);
}
}
}
@@ -230,44 +345,34 @@ void DRAW_STATS(TETROMINO *tetromino)
sprintf(SCORE_TEXT, "SCORE: %d", SCORE);
DrawText(SCORE_TEXT, 10, 10, FONT_SIZE, BLUE);
- char CURRENT_Y_POSITION[16], CURRENT_X_POSITION[16];
- sprintf(CURRENT_Y_POSITION, "Y: %d", tetromino->y);
- sprintf(CURRENT_X_POSITION, "X: %d", tetromino->x);
- DrawText(CURRENT_Y_POSITION, 10, 30, FONT_SIZE, BLUE);
- DrawText(CURRENT_X_POSITION, 10, 50, FONT_SIZE, BLUE);
-}
+ char CURRENT_Y_POSITION[32], CURRENT_X_POSITION[32];
+ sprintf(CURRENT_Y_POSITION, "Y COÖRDINATE: %d", tetromino->y);
+ sprintf(CURRENT_X_POSITION, "X COÖRDINATE: %d", tetromino->x);
+ DrawText(CURRENT_Y_POSITION, 10, 50, FONT_SIZE, BLUE);
+ DrawText(CURRENT_X_POSITION, 10, 80, FONT_SIZE, BLUE);
-void CHECK_FULL_LINE(int **GRID)
-{
- int LAST_LINE_Y = ROWS - 2;
- bool FULL_LINE = true;
+ int POS_X = SCREEN_WIDTH / 2;
+ int POS_Y = SCREEN_HEIGHT / 2;
- for (int x = 0; x <= COLUMNS; x++)
- {
- if (GRID[LAST_LINE_Y][x] == 0)
- {
- FULL_LINE = false;
- }
-
- }
- if (!FULL_LINE){
- for (int x = 0; x <= COLUMNS; x++)
- {
- GRID[LAST_LINE_Y][x] = GRID[LAST_LINE_Y][0];
- }
- }
+ const char ERROR_TEXT[] = "LOW FPS";
+ if (GetFPS() < 40)
+ DrawText(ERROR_TEXT, POS_X, POS_Y, FONT_SIZE, RED);
}
int main()
{
+ // Initialize the window and set the wanted FPS
InitWindow(SCREEN_WIDTH, SCREEN_HEIGHT, "Tetris");
SetTargetFPS(FPS);
+
+ // Spawn a new tetromino
TETROMINO ACTIVE_TETROMINO = SPAWN_TETROMINO();
+
int **GRID = CREATE_TETROMINOS_GRID(ROWS, COLUMNS);
if (!GRID)
{
- printf("FAILED TO ALLOCATE MEMORY FOR THE GRID");
+ printf("Failed to allocate memory for the grid.");
CloseWindow();
return 1;
}
@@ -277,14 +382,14 @@ int main()
BeginDrawing();
ClearBackground(BLACK);
- DRAW_GRID_BACKGROUND();
+ DRAW_BACKGROUND_GRID();
DRAW_SAVED_TETROMINO(GRID, &ACTIVE_TETROMINO);
DRAW_TETROMINO(&ACTIVE_TETROMINO);
DRAW_STATS(&ACTIVE_TETROMINO);
MOVE_TETROMINO(&ACTIVE_TETROMINO, GRID);
- if (ACTIVE_TETROMINO.y == ROWS - 2 && COLLISION_DETECTION(&ACTIVE_TETROMINO,GRID) == 0)
+ if (ACTIVE_TETROMINO.y == ROWS - 2 || COLLISION_DETECTION(&ACTIVE_TETROMINO, GRID) != 0)
{
SCORE++;
SAVE_TETROMINO(&ACTIVE_TETROMINO, GRID);